<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.tachyony.co.uk/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Tachyony</id>
	<title>Wikipedia - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.tachyony.co.uk/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Tachyony"/>
	<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/wiki/Special:Contributions/Tachyony"/>
	<updated>2026-07-07T06:54:34Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.44.0</generator>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=Template:About_year&amp;diff=120560</id>
		<title>Template:About year</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=Template:About_year&amp;diff=120560"/>
		<updated>2026-06-28T11:30:59Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: Protected &amp;quot;Template:About year&amp;quot;: Highly visible template ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{#if:{{{2|{{{4|{{{6|{{#ifexist:{{{1|{{PAGENAME}}}}} (disambiguation)|HasDisambig|{{#ifexist:{{{1|{{PAGENAME}}}}} (number)|{{#if:{{#invoke:redirect|isRedirect|{{{1|{{PAGENAME}}}}} (number)}}||NotRedirect}}}}|}}}}}}}}}}}|{{Hatnote|This article is about the year {{{1|{{PAGENAME}}}}}. {{#ifexist:{{{1|{{PAGENAME}}}}} (number)|{{#if:{{#invoke:redirect|isRedirect|{{{1|{{PAGENAME}}}}} (number)}}||For the number, see [[{{{1|{{PAGENAME}}}}} (number)]].}}}} {{#if:{{{2|}}}|For {{{2}}}, see [[{{{3}}}]].}} {{#if:{{{4|}}}|For {{{4}}}, see [[{{{5}}}]].}} {{#if:{{{6|}}}|For {{{6}}}, see [[{{{7}}}]].}} {{#ifexist:{{{1|{{PAGENAME}}}}} (disambiguation)|For other uses, see [[{{{1|{{PAGENAME}}}}} (disambiguation)]].}}}}|}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=Template:About_year&amp;diff=120559</id>
		<title>Template:About year</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=Template:About_year&amp;diff=120559"/>
		<updated>2026-06-28T11:30:40Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: ←Created page with &amp;#039;&amp;lt;includeonly&amp;gt;{{#if:{{{2|{{{4|{{{6|{{#ifexist:{{{1|{{PAGENAME}}}}} (disambiguation)|HasDisambig|{{#ifexist:{{{1|{{PAGENAME}}}}} (number)|{{#if:{{#invoke:redirect|isRedirect|{{{1|{{PAGENAME}}}}} (number)}}||NotRedirect}}}}|}}}}}}}}}}}|{{Hatnote|This article is about the year {{{1|{{PAGENAME}}}}}. {{#ifexist:{{{1|{{PAGENAME}}}}} (number)|{{#if:{{#invoke:redirect|isRedirect|{{{1|{{PAGENAME}}}}} (number)}}||For the number, see {{PAGENAME}}}}} (number).}...&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{#if:{{{2|{{{4|{{{6|{{#ifexist:{{{1|{{PAGENAME}}}}} (disambiguation)|HasDisambig|{{#ifexist:{{{1|{{PAGENAME}}}}} (number)|{{#if:{{#invoke:redirect|isRedirect|{{{1|{{PAGENAME}}}}} (number)}}||NotRedirect}}}}|}}}}}}}}}}}|{{Hatnote|This article is about the year {{{1|{{PAGENAME}}}}}. {{#ifexist:{{{1|{{PAGENAME}}}}} (number)|{{#if:{{#invoke:redirect|isRedirect|{{{1|{{PAGENAME}}}}} (number)}}||For the number, see [[{{{1|{{PAGENAME}}}}} (number)]].}}}} {{#if:{{{2|}}}|For {{{2}}}, see [[{{{3}}}]].}} {{#if:{{{4|}}}|For {{{4}}}, see [[{{{5}}}]].}} {{#if:{{{6|}}}|For {{{6}}}, see [[{{{7}}}]].}} {{#ifexist:{{{1|{{PAGENAME}}}}} (disambiguation)|For other uses, see [[{{{1|{{PAGENAME}}}}} (disambiguation)]].}}}}|}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=Template:Convert_abbreviated&amp;diff=120558</id>
		<title>Template:Convert abbreviated</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=Template:Convert_abbreviated&amp;diff=120558"/>
		<updated>2026-06-28T11:29:53Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: Protected &amp;quot;Template:Convert abbreviated&amp;quot;: Highly visible template ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{{{{♥|safesubst:}}}#invoke:convert|convert|abbr=on always|warnings=1}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;{{documentation}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=Template:Convert_abbreviated&amp;diff=120557</id>
		<title>Template:Convert abbreviated</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=Template:Convert_abbreviated&amp;diff=120557"/>
		<updated>2026-06-28T11:29:32Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: ←Created page with &amp;#039;&amp;lt;includeonly&amp;gt;{{{{{♥|safesubst:}}}#invoke:convert|convert|abbr=on always|warnings=1}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;{{documentation}}&amp;lt;/noinclude&amp;gt;&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{{{{♥|safesubst:}}}#invoke:convert|convert|abbr=on always|warnings=1}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;{{documentation}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=Template:Cvt&amp;diff=120556</id>
		<title>Template:Cvt</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=Template:Cvt&amp;diff=120556"/>
		<updated>2026-06-28T11:28:41Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: Protected &amp;quot;Template:Cvt&amp;quot;: Highly visible template ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite)) [cascading]&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Template:Convert abbreviated]]&lt;br /&gt;
&lt;br /&gt;
{{Redirect category shell|&lt;br /&gt;
{{R from move}}&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=Template:Cvt&amp;diff=120555</id>
		<title>Template:Cvt</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=Template:Cvt&amp;diff=120555"/>
		<updated>2026-06-28T11:28:08Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: ←Redirected page to Template:Convert abbreviated&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Template:Convert abbreviated]]&lt;br /&gt;
&lt;br /&gt;
{{Redirect category shell|&lt;br /&gt;
{{R from move}}&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=Template:Langx&amp;diff=120554</id>
		<title>Template:Langx</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=Template:Langx&amp;diff=120554"/>
		<updated>2026-06-28T11:26:40Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: Changed protection settings for &amp;quot;Template:Langx&amp;quot;: Highly visible template ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite)) [cascading]&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{#invoke:lang|langx}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=Template:Year_nav&amp;diff=120553</id>
		<title>Template:Year nav</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=Template:Year_nav&amp;diff=120553"/>
		<updated>2026-06-28T11:26:16Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: Protected &amp;quot;Template:Year nav&amp;quot;: Highly visible template ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite)) [cascading]&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{short description|Calendar year|2=noreplace}}&lt;br /&gt;
{{sidebar&lt;br /&gt;
|title=[[List of decades, centuries, and millennia|Years]]&lt;br /&gt;
|name=Year nav&lt;br /&gt;
|contentclass=hlist&lt;br /&gt;
&lt;br /&gt;
|heading1=Millennium&lt;br /&gt;
|content1= {{dr|y|m|{{{1|{{PAGENAME}}}}}|0|ys}}&lt;br /&gt;
&lt;br /&gt;
|heading2=Centuries&lt;br /&gt;
|content2=&lt;br /&gt;
* {{dr|y|c|{{{1|{{PAGENAME}}}}}|-1|ys}}&lt;br /&gt;
* &#039;&#039;&#039;{{dr|y|c|{{{1|{{PAGENAME}}}}}|0|ys}} &#039;&#039;&#039;&lt;br /&gt;
* {{dr|y|c|{{{1|{{PAGENAME}}}}}|1|ys}}&lt;br /&gt;
&lt;br /&gt;
|heading3=Decades&lt;br /&gt;
|content3=&lt;br /&gt;
* {{dr|y|d|{{{1|{{PAGENAME}}}}}|-2|ys}}&lt;br /&gt;
* {{dr|y|d|{{{1|{{PAGENAME}}}}}|-1|ys}}&lt;br /&gt;
* &#039;&#039;&#039;{{dr|y|d|{{{1|{{PAGENAME}}}}}|0|ys}} &#039;&#039;&#039;&lt;br /&gt;
* {{dr|y|d|{{{1|{{PAGENAME}}}}}|1|ys}}&lt;br /&gt;
* {{dr|y|d|{{{1|{{PAGENAME}}}}}|2|ys}}&lt;br /&gt;
&lt;br /&gt;
|heading4=[[List of years|Years]]&lt;br /&gt;
|content4=&lt;br /&gt;
* {{dr|y|y|{{{1|{{PAGENAME}}}}}|-3|{{#ifexpr: {{{1|{{PAGENAME}}}}} &amp;lt;= 12 |ysa|ys}}}}&lt;br /&gt;
* {{dr|y|y|{{{1|{{PAGENAME}}}}}|-2|{{#ifexpr: {{{1|{{PAGENAME}}}}} &amp;lt;= 12 |ysa|ys}}}}&lt;br /&gt;
* {{dr|y|y|{{{1|{{PAGENAME}}}}}|-1|{{#ifexpr: {{{1|{{PAGENAME}}}}} &amp;lt;= 12 |ysa|ys}}}}&lt;br /&gt;
* &#039;&#039;&#039;{{dr|y|y|{{{1|{{PAGENAME}}}}}|0|{{#ifexpr: {{{1|{{PAGENAME}}}}} &amp;lt;= 100 |ysa|ys}}}} &#039;&#039;&#039;&lt;br /&gt;
* {{dr|y|y|{{{1|{{PAGENAME}}}}}|1|{{#ifexpr: {{{1|{{PAGENAME}}}}} &amp;lt;= 9 |ysa|ys}}}}&lt;br /&gt;
* {{dr|y|y|{{{1|{{PAGENAME}}}}}|2|{{#ifexpr: {{{1|{{PAGENAME}}}}} &amp;lt;= 8 |ysa|ys}}}}&lt;br /&gt;
* {{dr|y|y|{{{1|{{PAGENAME}}}}}|3|{{#ifexpr: {{{1|{{PAGENAME}}}}} &amp;lt;= 7 |ysa|ys}}}}&lt;br /&gt;
}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=Template:Year_nav&amp;diff=120552</id>
		<title>Template:Year nav</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=Template:Year_nav&amp;diff=120552"/>
		<updated>2026-06-28T11:25:45Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: ←Created page with &amp;#039;{{short description|Calendar year|2=noreplace}} {{sidebar |title=Years |name=Year nav |contentclass=hlist  |heading1=Millennium |content1= {{dr|y|m|{{{1|{{PAGENAME}}}}}|0|ys}}  |heading2=Centuries |content2= * {{dr|y|c|{{{1|{{PAGENAME}}}}}|-1|ys}} * &amp;#039;&amp;#039;&amp;#039;{{dr|y|c|{{{1|{{PAGENAME}}}}}|0|ys}} &amp;#039;&amp;#039;&amp;#039; * {{dr|y|c|{{{1|{{PAGENAME}}}}}|1|ys}}  |heading3=Decades |content3= * {{dr|y|d|{{{1|{{PAGENAME}}}}}|-2|ys}} * {{dr|y|d|{...&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{short description|Calendar year|2=noreplace}}&lt;br /&gt;
{{sidebar&lt;br /&gt;
|title=[[List of decades, centuries, and millennia|Years]]&lt;br /&gt;
|name=Year nav&lt;br /&gt;
|contentclass=hlist&lt;br /&gt;
&lt;br /&gt;
|heading1=Millennium&lt;br /&gt;
|content1= {{dr|y|m|{{{1|{{PAGENAME}}}}}|0|ys}}&lt;br /&gt;
&lt;br /&gt;
|heading2=Centuries&lt;br /&gt;
|content2=&lt;br /&gt;
* {{dr|y|c|{{{1|{{PAGENAME}}}}}|-1|ys}}&lt;br /&gt;
* &#039;&#039;&#039;{{dr|y|c|{{{1|{{PAGENAME}}}}}|0|ys}} &#039;&#039;&#039;&lt;br /&gt;
* {{dr|y|c|{{{1|{{PAGENAME}}}}}|1|ys}}&lt;br /&gt;
&lt;br /&gt;
|heading3=Decades&lt;br /&gt;
|content3=&lt;br /&gt;
* {{dr|y|d|{{{1|{{PAGENAME}}}}}|-2|ys}}&lt;br /&gt;
* {{dr|y|d|{{{1|{{PAGENAME}}}}}|-1|ys}}&lt;br /&gt;
* &#039;&#039;&#039;{{dr|y|d|{{{1|{{PAGENAME}}}}}|0|ys}} &#039;&#039;&#039;&lt;br /&gt;
* {{dr|y|d|{{{1|{{PAGENAME}}}}}|1|ys}}&lt;br /&gt;
* {{dr|y|d|{{{1|{{PAGENAME}}}}}|2|ys}}&lt;br /&gt;
&lt;br /&gt;
|heading4=[[List of years|Years]]&lt;br /&gt;
|content4=&lt;br /&gt;
* {{dr|y|y|{{{1|{{PAGENAME}}}}}|-3|{{#ifexpr: {{{1|{{PAGENAME}}}}} &amp;lt;= 12 |ysa|ys}}}}&lt;br /&gt;
* {{dr|y|y|{{{1|{{PAGENAME}}}}}|-2|{{#ifexpr: {{{1|{{PAGENAME}}}}} &amp;lt;= 12 |ysa|ys}}}}&lt;br /&gt;
* {{dr|y|y|{{{1|{{PAGENAME}}}}}|-1|{{#ifexpr: {{{1|{{PAGENAME}}}}} &amp;lt;= 12 |ysa|ys}}}}&lt;br /&gt;
* &#039;&#039;&#039;{{dr|y|y|{{{1|{{PAGENAME}}}}}|0|{{#ifexpr: {{{1|{{PAGENAME}}}}} &amp;lt;= 100 |ysa|ys}}}} &#039;&#039;&#039;&lt;br /&gt;
* {{dr|y|y|{{{1|{{PAGENAME}}}}}|1|{{#ifexpr: {{{1|{{PAGENAME}}}}} &amp;lt;= 9 |ysa|ys}}}}&lt;br /&gt;
* {{dr|y|y|{{{1|{{PAGENAME}}}}}|2|{{#ifexpr: {{{1|{{PAGENAME}}}}} &amp;lt;= 8 |ysa|ys}}}}&lt;br /&gt;
* {{dr|y|y|{{{1|{{PAGENAME}}}}}|3|{{#ifexpr: {{{1|{{PAGENAME}}}}} &amp;lt;= 7 |ysa|ys}}}}&lt;br /&gt;
}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=Template:Langx&amp;diff=120551</id>
		<title>Template:Langx</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=Template:Langx&amp;diff=120551"/>
		<updated>2026-06-28T11:24:57Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: Protected &amp;quot;Template:Langx&amp;quot; ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{#invoke:lang|langx}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=Template:Langx&amp;diff=120550</id>
		<title>Template:Langx</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=Template:Langx&amp;diff=120550"/>
		<updated>2026-06-28T11:24:39Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: ←Created page with &amp;#039;&amp;lt;includeonly&amp;gt;{{#invoke:lang|langx}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt; {{Documentation}} &amp;lt;/noinclude&amp;gt;&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{#invoke:lang|langx}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-section-browsing&amp;diff=120547</id>
		<title>MediaWiki:Gadget-section-browsing</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-section-browsing&amp;diff=120547"/>
		<updated>2026-06-25T10:30:56Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: Protected &amp;quot;MediaWiki:Gadget-section-browsing&amp;quot;: Highly visible template ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite)) [cascading]&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Browsing&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-section-browsing&amp;diff=120546</id>
		<title>MediaWiki:Gadget-section-browsing</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-section-browsing&amp;diff=120546"/>
		<updated>2026-06-25T10:30:27Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: ←Created page with &amp;#039;Browsing&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Browsing&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=Template:%27,_%27&amp;diff=120545</id>
		<title>Template:&#039;, &#039;</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=Template:%27,_%27&amp;diff=120545"/>
		<updated>2026-06-25T10:27:39Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Template:Void]]&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=Template:Void&amp;diff=120543</id>
		<title>Template:Void</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=Template:Void&amp;diff=120543"/>
		<updated>2026-06-25T10:27:39Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{documentation}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-navpop.css&amp;diff=120541</id>
		<title>MediaWiki:Gadget-navpop.css</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-navpop.css&amp;diff=120541"/>
		<updated>2026-06-25T10:27:39Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;.popupMoreLink {&lt;br /&gt;
  display: block;&lt;br /&gt;
  text-align: right;&lt;br /&gt;
  cursor: pointer;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ins.popupDiff {&lt;br /&gt;
  background: #afe;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
del.popupDiff {&lt;br /&gt;
  background: #ffe6e6;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Dark mode fixes */&lt;br /&gt;
html.skin-theme-clientpref-night ins.popupDiff {&lt;br /&gt;
  background: #026c5f;&lt;br /&gt;
}&lt;br /&gt;
html.skin-theme-clientpref-night del.popupDiff {&lt;br /&gt;
  background: #89474b;&lt;br /&gt;
}&lt;br /&gt;
@media (prefers-color-scheme: dark) {&lt;br /&gt;
  html.skin-theme-clientpref-os ins.popupDiff {&lt;br /&gt;
    background: #026c5f;&lt;br /&gt;
  }&lt;br /&gt;
  html.skin-theme-clientpref-os del.popupDiff {&lt;br /&gt;
    background: #89474b;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#selectionPreview {&lt;br /&gt;
  border: 2px solid var(--border-color-subtle, #c8ccd1);&lt;br /&gt;
  background-color: var(--background-color-progressive-subtle, #eaf3ff);&lt;br /&gt;
  padding: 6px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.navpopup {&lt;br /&gt;
  border: 1px solid var(--border-color-base, #a2a9b1);&lt;br /&gt;
  background-color: var(--background-color-base, #fff);&lt;br /&gt;
  color: var(--color-base, #202122);&lt;br /&gt;
  padding: 10px;&lt;br /&gt;
  padding-bottom: 5px;&lt;br /&gt;
  font-size: 11px;&lt;br /&gt;
  box-shadow: 0 3px 8px rgba( 50, 50, 50, 0.35 );&lt;br /&gt;
  word-wrap: break-word;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.navpopup hr {&lt;br /&gt;
  color: #aaa !important;&lt;br /&gt;
  background-color: #aaa !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Configure Drag bar color */&lt;br /&gt;
.popupDrag {&lt;br /&gt;
  background-color: #ffbe20;&lt;br /&gt;
  height: 5px;&lt;br /&gt;
  margin-top: -5px;&lt;br /&gt;
  margin-bottom: 5px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.popupDragHandle {&lt;br /&gt;
  cursor: move;&lt;br /&gt;
  position: relative;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* menu magic - many thanks to [[User:Zocky]]! */&lt;br /&gt;
&lt;br /&gt;
/* popups */&lt;br /&gt;
.popup_menu {&lt;br /&gt;
  display: none;&lt;br /&gt;
  position: absolute;&lt;br /&gt;
  left: 0;&lt;br /&gt;
  margin: 0;&lt;br /&gt;
  margin-top: 1.4em;&lt;br /&gt;
  line-height: 1.25em;&lt;br /&gt;
  top: 0;&lt;br /&gt;
  z-index: 2;&lt;br /&gt;
  width: 10em;&lt;br /&gt;
  background: var(--background-color-base, #fff);&lt;br /&gt;
  border: 1px solid grey;&lt;br /&gt;
  padding: 0 !important;&lt;br /&gt;
  margin-left: -6px;&lt;br /&gt;
  border-width: 1px 1px 1px 6px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.popup_menu li { /* both: popup_menu_row and popup_menu_item */&lt;br /&gt;
  list-style: none;&lt;br /&gt;
  margin:0;&lt;br /&gt;
  padding:0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.popup_menu a {&lt;br /&gt;
  display: block;&lt;br /&gt;
  padding: 3px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.popup_menu_row a {&lt;br /&gt;
  display: inline-block;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.popup_menu_row {&lt;br /&gt;
  color: #aaa;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.popup_drop {&lt;br /&gt;
  display: inline;&lt;br /&gt;
  position: relative;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.popup_drop a,&lt;br /&gt;
.popup_drop a:visited {&lt;br /&gt;
  padding: 3px;&lt;br /&gt;
  margin: 0;&lt;br /&gt;
  font-weight: bold;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.popup_drop:hover .popup_menu,&lt;br /&gt;
.popup_drop .popup_menu:hover {&lt;br /&gt;
  display: inline;&lt;br /&gt;
  padding: 2px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.popup_drop:hover {&lt;br /&gt;
  background: #ccf;&lt;br /&gt;
  color: #44f;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* other colours, styles and so on */&lt;br /&gt;
.popup_menu a:hover {&lt;br /&gt;
  background: grey;&lt;br /&gt;
  color: #fff;&lt;br /&gt;
  text-decoration: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.popup_mainlink {&lt;br /&gt;
  font-size: 140%;&lt;br /&gt;
  font-weight: bold;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.popup_mainlink a {&lt;br /&gt;
  color: var(--color-emphasized, #000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
a.popup_change_title_link {&lt;br /&gt;
  color: #152;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Dark mode fixes */&lt;br /&gt;
html.skin-theme-clientpref-night a.popup_change_title_link {&lt;br /&gt;
  color: #25b84a;&lt;br /&gt;
}&lt;br /&gt;
@media (prefers-color-scheme: dark) {&lt;br /&gt;
  html.skin-theme-clientpref-os a.popup_change_title_link {&lt;br /&gt;
    color: #25b84a;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.popup_diff_dates {&lt;br /&gt;
  font-style: italic;&lt;br /&gt;
  background: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.popup_menu_item a {&lt;br /&gt;
  display: block;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.popup_history_row_even {&lt;br /&gt;
  background: var(--background-color-neutral, #eaecf0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.popup_history_date {&lt;br /&gt;
  font-weight: bold;&lt;br /&gt;
  font-size: 120%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
	Important for history preview when summaries are all empty;&lt;br /&gt;
	e.g. https://en.wikipedia.org/w/index.php?title=User:GWicke/sw.js&lt;br /&gt;
	The path is:&lt;br /&gt;
	.popupPreview &amp;gt; table &amp;gt; tbody &amp;gt; tr:is(.popup_history_row_odd, .popup_history_row_even)&lt;br /&gt;
*/&lt;br /&gt;
.popupPreview &amp;gt; table,&lt;br /&gt;
.popupPreview &amp;gt; table &amp;gt; tbody {&lt;br /&gt;
	display: block;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.popup_history_row_odd,&lt;br /&gt;
.popup_history_row_even {&lt;br /&gt;
	display: flex;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.popup_history_row_even td:nth-child(3),&lt;br /&gt;
.popup_history_row_odd td:nth-child(3) {&lt;br /&gt;
	flex: 3;&lt;br /&gt;
	word-break: break-word;&lt;br /&gt;
}&lt;br /&gt;
.popup_history_row_even td:nth-child(4),&lt;br /&gt;
.popup_history_row_odd td:nth-child(4) {&lt;br /&gt;
	flex: 7;&lt;br /&gt;
	word-break: break-word;&lt;br /&gt;
}&lt;br /&gt;
.popup_history_row_even &amp;gt; td:not(:last-child),&lt;br /&gt;
.popup_history_row_odd &amp;gt; td:not(:last-child) {&lt;br /&gt;
	margin-right: 2px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* disable interwiki styling */&lt;br /&gt;
.popupPreview a.extiw,&lt;br /&gt;
.popupPreview a.extiw:active {&lt;br /&gt;
  color: #36b;&lt;br /&gt;
  background: none;&lt;br /&gt;
  padding: 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.popupPreview .external {&lt;br /&gt;
  color: #36b;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* this can be used in the content area to switch off&lt;br /&gt;
special external link styling */&lt;br /&gt;
.popupPreview .plainlinks a {&lt;br /&gt;
  background: none !important;&lt;br /&gt;
  padding: 0 !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
	Mouse safe zones for popup menu.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/* eye guide suggestion */	&lt;br /&gt;
.popup_menu:hover {&lt;br /&gt;
	box-shadow: 0 0 5px 5px rgba(179, 179, 255, 0.3);&lt;br /&gt;
}&lt;br /&gt;
/* Dark mode fixes */&lt;br /&gt;
html.skin-theme-clientpref-night .popup_menu:hover {&lt;br /&gt;
	box-shadow: 0 0 5px 5px rgba(0, 0, 90, 0.3);&lt;br /&gt;
}&lt;br /&gt;
@media (prefers-color-scheme: dark) {&lt;br /&gt;
	html.skin-theme-clientpref-os .popup_menu:hover {&lt;br /&gt;
		box-shadow: 0 0 5px 5px rgba(0, 0, 90, 0.3);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* trapezoid guide for the cursor */	&lt;br /&gt;
.popup_menu::before {&lt;br /&gt;
	content: &#039;&#039;;&lt;br /&gt;
	display: block;&lt;br /&gt;
	position: absolute;&lt;br /&gt;
	height: 1.5em;&lt;br /&gt;
	top: -1.4em;&lt;br /&gt;
	left: -1.2em;&lt;br /&gt;
	width: calc(2 * var(--navpop-m-len, 6ch));&lt;br /&gt;
	transform: perspective(1px) rotateX(1deg);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* make the trapezoid go behing menu items */&lt;br /&gt;
.popup_menu::before {&lt;br /&gt;
	z-index: 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.popup_menu li {&lt;br /&gt;
	position: relative;&lt;br /&gt;
	z-index: 2;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* additional hover margin on the sides */&lt;br /&gt;
.popup_menu li::before {&lt;br /&gt;
	content: &#039;&#039;;&lt;br /&gt;
	display: block;&lt;br /&gt;
	position: absolute;&lt;br /&gt;
	top: 0;&lt;br /&gt;
	height: calc(100% + .5em);&lt;br /&gt;
	left: -1.7em;&lt;br /&gt;
	width: 1.7em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.popup_menu li::after {&lt;br /&gt;
	content: &#039;&#039;;&lt;br /&gt;
	display: block;&lt;br /&gt;
	position: absolute;&lt;br /&gt;
	top: 0;&lt;br /&gt;
	height: calc(100% + .5em);&lt;br /&gt;
	left: calc(10em - 1px);	/* depends on the width of the menu */&lt;br /&gt;
	width: 1em;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-popups.js&amp;diff=120539</id>
		<title>MediaWiki:Gadget-popups.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-popups.js&amp;diff=120539"/>
		<updated>2026-06-25T10:27:39Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// STARTFILE: main.js&lt;br /&gt;
// **********************************************************************&lt;br /&gt;
// **                                                                  **&lt;br /&gt;
// **             changes to this file affect many users.              **&lt;br /&gt;
// **           please discuss on the talk page before editing         **&lt;br /&gt;
// **                                                                  **&lt;br /&gt;
// **********************************************************************&lt;br /&gt;
// **                                                                  **&lt;br /&gt;
// ** if you do edit this file, be sure that your editor recognizes it **&lt;br /&gt;
// ** as utf8, or the weird and wonderful characters in the namespaces **&lt;br /&gt;
// **   below will be completely broken. You can check with the show   **&lt;br /&gt;
// **            changes button before submitting the edit.            **&lt;br /&gt;
// **                      test: مدیا מיוחד Мэдыя                      **&lt;br /&gt;
// **                                                                  **&lt;br /&gt;
// **********************************************************************&lt;br /&gt;
/* eslint-env browser  */&lt;br /&gt;
/* global $, jQuery, mw, window */&lt;br /&gt;
&lt;br /&gt;
// Fix later&lt;br /&gt;
/* global log, errlog, popupStrings, wikEdUseWikEd, WikEdUpdateFrame */&lt;br /&gt;
&lt;br /&gt;
$(() =&amp;gt; {&lt;br /&gt;
	//////////////////////////////////////////////////&lt;br /&gt;
	// Globals&lt;br /&gt;
	//&lt;br /&gt;
&lt;br /&gt;
	// Trying to shove as many of these as possible into the pg (popup globals) object&lt;br /&gt;
	const pg = {&lt;br /&gt;
		api: {}, // MediaWiki API requests&lt;br /&gt;
		re: {}, // regexps&lt;br /&gt;
		ns: {}, // namespaces&lt;br /&gt;
		string: {}, // translatable strings&lt;br /&gt;
		wiki: {}, // local site info&lt;br /&gt;
		user: {}, // current user info&lt;br /&gt;
		misc: {}, // YUCK PHOOEY&lt;br /&gt;
		option: {}, // options, see newOption etc&lt;br /&gt;
		optionDefault: {}, // default option values&lt;br /&gt;
		flag: {}, // misc flags&lt;br /&gt;
		cache: {}, // page and image cache&lt;br /&gt;
		structures: {}, // navlink structures&lt;br /&gt;
		timer: {}, // all sorts of timers (too damn many)&lt;br /&gt;
		counter: {}, // .. and all sorts of counters&lt;br /&gt;
		current: {}, // state info&lt;br /&gt;
		fn: {}, // functions&lt;br /&gt;
		endoflist: null,&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/* Bail if the gadget/script is being loaded twice */&lt;br /&gt;
	/* An element with id &amp;quot;pg&amp;quot; would add a window.pg property, ignore such property */&lt;br /&gt;
	if (window.pg &amp;amp;&amp;amp; !(window.pg instanceof HTMLElement)) {&lt;br /&gt;
		return;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Export to global context */&lt;br /&gt;
	window.pg = pg;&lt;br /&gt;
&lt;br /&gt;
	/// Local Variables: ///&lt;br /&gt;
	/// mode:c ///&lt;br /&gt;
	/// End: ///&lt;br /&gt;
	// ENDFILE: main.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: actions.js&lt;br /&gt;
	function setupTooltips(container, remove, force, popData) {&lt;br /&gt;
		log(&#039;setupTooltips, container=&#039; + container + &#039;, remove=&#039; + remove);&lt;br /&gt;
		if (!container) {&lt;br /&gt;
			// the main initial call&lt;br /&gt;
			if (&lt;br /&gt;
				getValueOf(&#039;popupOnEditSelection&#039;) &amp;amp;&amp;amp;&lt;br /&gt;
				document &amp;amp;&amp;amp;&lt;br /&gt;
				document.editform &amp;amp;&amp;amp;&lt;br /&gt;
				document.editform.wpTextbox1&lt;br /&gt;
			) {&lt;br /&gt;
				document.editform.wpTextbox1.onmouseup = doSelectionPopup;&lt;br /&gt;
			}&lt;br /&gt;
			// article/content is a structure-dependent thing&lt;br /&gt;
			container = defaultPopupsContainer();&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (!remove &amp;amp;&amp;amp; !force &amp;amp;&amp;amp; container.ranSetupTooltipsAlready) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		container.ranSetupTooltipsAlready = !remove;&lt;br /&gt;
&lt;br /&gt;
		let anchors;&lt;br /&gt;
		anchors = container.getElementsByTagName(&#039;A&#039;);&lt;br /&gt;
		setupTooltipsLoop(anchors, 0, 250, 100, remove, popData);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function defaultPopupsContainer() {&lt;br /&gt;
		if (getValueOf(&#039;popupOnlyArticleLinks&#039;)) {&lt;br /&gt;
			return (&lt;br /&gt;
				document.querySelector(&#039;.skin-vector-2022 .vector-body&#039;) ||&lt;br /&gt;
				document.getElementById(&#039;mw_content&#039;) ||&lt;br /&gt;
				document.getElementById(&#039;content&#039;) ||&lt;br /&gt;
				document.getElementById(&#039;article&#039;) ||&lt;br /&gt;
				document&lt;br /&gt;
			);&lt;br /&gt;
		}&lt;br /&gt;
		return document;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function setupTooltipsLoop(anchors, begin, howmany, sleep, remove, popData) {&lt;br /&gt;
		log(simplePrintf(&#039;setupTooltipsLoop(%s,%s,%s,%s,%s)&#039;, arguments));&lt;br /&gt;
		const finish = begin + howmany;&lt;br /&gt;
		const loopend = Math.min(finish, anchors.length);&lt;br /&gt;
		let j = loopend - begin;&lt;br /&gt;
		log(&lt;br /&gt;
			&#039;setupTooltips: anchors.length=&#039; +&lt;br /&gt;
				anchors.length +&lt;br /&gt;
				&#039;, begin=&#039; +&lt;br /&gt;
				begin +&lt;br /&gt;
				&#039;, howmany=&#039; +&lt;br /&gt;
				howmany +&lt;br /&gt;
				&#039;, loopend=&#039; +&lt;br /&gt;
				loopend +&lt;br /&gt;
				&#039;, remove=&#039; +&lt;br /&gt;
				remove&lt;br /&gt;
		);&lt;br /&gt;
		const doTooltip = remove ? removeTooltip : addTooltip;&lt;br /&gt;
		// try a faster (?) loop construct&lt;br /&gt;
		if (j &amp;gt; 0) {&lt;br /&gt;
			do {&lt;br /&gt;
				const a = anchors[loopend - j];&lt;br /&gt;
				if (typeof a === &#039;undefined&#039; || !a || !a.href) {&lt;br /&gt;
					log(&#039;got null anchor at index &#039; + loopend - j);&lt;br /&gt;
					continue;&lt;br /&gt;
				}&lt;br /&gt;
				doTooltip(a, popData);&lt;br /&gt;
			} while (--j);&lt;br /&gt;
		}&lt;br /&gt;
		if (finish &amp;lt; anchors.length) {&lt;br /&gt;
			setTimeout(() =&amp;gt; {&lt;br /&gt;
				setupTooltipsLoop(anchors, finish, howmany, sleep, remove, popData);&lt;br /&gt;
			}, sleep);&lt;br /&gt;
		} else {&lt;br /&gt;
			if (!remove &amp;amp;&amp;amp; !getValueOf(&#039;popupTocLinks&#039;)) {&lt;br /&gt;
				rmTocTooltips();&lt;br /&gt;
			}&lt;br /&gt;
			pg.flag.finishedLoading = true;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// eliminate popups from the TOC&lt;br /&gt;
	// This also kills any onclick stuff that used to be going on in the toc&lt;br /&gt;
	function rmTocTooltips() {&lt;br /&gt;
		const toc = document.getElementById(&#039;toc&#039;);&lt;br /&gt;
		if (toc) {&lt;br /&gt;
			const tocLinks = toc.getElementsByTagName(&#039;A&#039;);&lt;br /&gt;
			const tocLen = tocLinks.length;&lt;br /&gt;
			for (let j = 0; j &amp;lt; tocLen; ++j) {&lt;br /&gt;
				removeTooltip(tocLinks[j], true);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function addTooltip(a, popData) {&lt;br /&gt;
		if (!isPopupLink(a)) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		a.onmouseover = mouseOverWikiLink;&lt;br /&gt;
		a.onmouseout = mouseOutWikiLink;&lt;br /&gt;
		a.onmousedown = killPopup;&lt;br /&gt;
		a.hasPopup = true;&lt;br /&gt;
		a.popData = popData;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function removeTooltip(a) {&lt;br /&gt;
		if (!a.hasPopup) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		a.onmouseover = null;&lt;br /&gt;
		a.onmouseout = null;&lt;br /&gt;
		if (a.originalTitle) {&lt;br /&gt;
			a.title = a.originalTitle;&lt;br /&gt;
		}&lt;br /&gt;
		a.hasPopup = false;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function removeTitle(a) {&lt;br /&gt;
		if (!a.originalTitle) {&lt;br /&gt;
			a.originalTitle = a.title;&lt;br /&gt;
		}&lt;br /&gt;
		a.title = &#039;&#039;;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function restoreTitle(a) {&lt;br /&gt;
		if (a.title || !a.originalTitle) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		a.title = a.originalTitle;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function registerHooks(np) {&lt;br /&gt;
		const popupMaxWidth = getValueOf(&#039;popupMaxWidth&#039;);&lt;br /&gt;
&lt;br /&gt;
		if (typeof popupMaxWidth === &#039;number&#039;) {&lt;br /&gt;
			const setMaxWidth = function () {&lt;br /&gt;
				np.mainDiv.style.maxWidth = popupMaxWidth + &#039;px&#039;;&lt;br /&gt;
				np.maxWidth = popupMaxWidth;&lt;br /&gt;
			};&lt;br /&gt;
			np.addHook(setMaxWidth, &#039;unhide&#039;, &#039;before&#039;);&lt;br /&gt;
		}&lt;br /&gt;
		np.addHook(addPopupShortcuts, &#039;unhide&#039;, &#039;after&#039;);&lt;br /&gt;
		np.addHook(rmPopupShortcuts, &#039;hide&#039;, &#039;before&#039;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function removeModifierKeyHandler(a) {&lt;br /&gt;
		//remove listeners for modifier key if any that were added in mouseOverWikiLink&lt;br /&gt;
		document.removeEventListener(&#039;keydown&#039;, a.modifierKeyHandler, false);&lt;br /&gt;
		document.removeEventListener(&#039;keyup&#039;, a.modifierKeyHandler, false);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function mouseOverWikiLink(evt) {&lt;br /&gt;
		if (!evt &amp;amp;&amp;amp; window.event) {&lt;br /&gt;
			evt = window.event;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// if the modifier is needed, listen for it,&lt;br /&gt;
		// we will remove the listener when we mouseout of this link or kill popup.&lt;br /&gt;
		if (getValueOf(&#039;popupModifier&#039;)) {&lt;br /&gt;
			// if popupModifierAction = enable, we should popup when the modifier is pressed&lt;br /&gt;
			// if popupModifierAction = disable, we should popup unless the modifier is pressed&lt;br /&gt;
			const action = getValueOf(&#039;popupModifierAction&#039;);&lt;br /&gt;
			const key = action == &#039;disable&#039; ? &#039;keyup&#039; : &#039;keydown&#039;;&lt;br /&gt;
			const a = this;&lt;br /&gt;
			a.modifierKeyHandler = function (evt) {&lt;br /&gt;
				mouseOverWikiLink2(a, evt);&lt;br /&gt;
			};&lt;br /&gt;
			document.addEventListener(key, a.modifierKeyHandler, false);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		return mouseOverWikiLink2(this, evt);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Gets the references list item that the provided footnote link targets. This&lt;br /&gt;
	 * is typically a li element within the ol.references element inside the reflist.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param {Element} a - A footnote link.&lt;br /&gt;
	 * @return {Element|boolean} The targeted element, or false if one can&#039;t be found.&lt;br /&gt;
	 */&lt;br /&gt;
	function footnoteTarget(a) {&lt;br /&gt;
		const aTitle = Title.fromAnchor(a);&lt;br /&gt;
		// We want &amp;quot;.3A&amp;quot; rather than &amp;quot;%3A&amp;quot; or &amp;quot;?&amp;quot; here, so use the anchor property directly&lt;br /&gt;
		const anch = aTitle.anchor;&lt;br /&gt;
		if (!/^(cite_note-|_note-|endnote)/.test(anch)) {&lt;br /&gt;
			return false;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const lTitle = Title.fromURL(location.href);&lt;br /&gt;
		if (lTitle.toString(true) !== aTitle.toString(true)) {&lt;br /&gt;
			return false;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		let el = document.getElementById(anch);&lt;br /&gt;
		while (el &amp;amp;&amp;amp; typeof el.nodeName === &#039;string&#039;) {&lt;br /&gt;
			const nt = el.nodeName.toLowerCase();&lt;br /&gt;
			if (nt === &#039;li&#039;) {&lt;br /&gt;
				return el;&lt;br /&gt;
			} else if (nt === &#039;body&#039;) {&lt;br /&gt;
				return false;&lt;br /&gt;
			} else if (el.parentNode) {&lt;br /&gt;
				el = el.parentNode;&lt;br /&gt;
			} else {&lt;br /&gt;
				return false;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return false;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function footnotePreview(x, navpop) {&lt;br /&gt;
		setPopupHTML(&#039;&amp;lt;hr /&amp;gt;&#039; + x.innerHTML, &#039;popupPreview&#039;, navpop.idNumber);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function modifierPressed(evt) {&lt;br /&gt;
		const mod = getValueOf(&#039;popupModifier&#039;);&lt;br /&gt;
		if (!mod) {&lt;br /&gt;
			return false;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (!evt &amp;amp;&amp;amp; window.event) {&lt;br /&gt;
			evt = window.event;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		return evt &amp;amp;&amp;amp; mod &amp;amp;&amp;amp; evt[mod.toLowerCase() + &#039;Key&#039;];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Checks if the correct modifier pressed/unpressed if needed&lt;br /&gt;
	function isCorrectModifier(a, evt) {&lt;br /&gt;
		if (!getValueOf(&#039;popupModifier&#039;)) {&lt;br /&gt;
			return true;&lt;br /&gt;
		}&lt;br /&gt;
		// if popupModifierAction = enable, we should popup when the modifier is pressed&lt;br /&gt;
		// if popupModifierAction = disable, we should popup unless the modifier is pressed&lt;br /&gt;
		const action = getValueOf(&#039;popupModifierAction&#039;);&lt;br /&gt;
		return (&lt;br /&gt;
			(action == &#039;enable&#039; &amp;amp;&amp;amp; modifierPressed(evt)) || (action == &#039;disable&#039; &amp;amp;&amp;amp; !modifierPressed(evt))&lt;br /&gt;
		);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function mouseOverWikiLink2(a, evt) {&lt;br /&gt;
		if (!isCorrectModifier(a, evt)) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (getValueOf(&#039;removeTitles&#039;)) {&lt;br /&gt;
			removeTitle(a);&lt;br /&gt;
		}&lt;br /&gt;
		if (a == pg.current.link &amp;amp;&amp;amp; a.navpopup &amp;amp;&amp;amp; a.navpopup.isVisible()) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		pg.current.link = a;&lt;br /&gt;
&lt;br /&gt;
		if (getValueOf(&#039;simplePopups&#039;) &amp;amp;&amp;amp; !pg.option.popupStructure) {&lt;br /&gt;
			// reset *default value* of popupStructure&lt;br /&gt;
			setDefault(&#039;popupStructure&#039;, &#039;original&#039;);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const article = new Title().fromAnchor(a);&lt;br /&gt;
		// set global variable (ugh) to hold article (wikipage)&lt;br /&gt;
		pg.current.article = article;&lt;br /&gt;
&lt;br /&gt;
		if (!a.navpopup) {&lt;br /&gt;
			a.navpopup = newNavpopup(a, article);&lt;br /&gt;
			pg.current.linksHash[a.href] = a.navpopup;&lt;br /&gt;
			pg.current.links.push(a);&lt;br /&gt;
		}&lt;br /&gt;
		if (a.navpopup.pending === null || a.navpopup.pending !== 0) {&lt;br /&gt;
			// either fresh popups or those with unfinshed business are redone from scratch&lt;br /&gt;
			simplePopupContent(a, article);&lt;br /&gt;
		}&lt;br /&gt;
		a.navpopup.showSoonIfStable(a.navpopup.delay);&lt;br /&gt;
&lt;br /&gt;
		clearInterval(pg.timer.checkPopupPosition);&lt;br /&gt;
		pg.timer.checkPopupPosition = setInterval(checkPopupPosition, 600);&lt;br /&gt;
&lt;br /&gt;
		if (getValueOf(&#039;simplePopups&#039;)) {&lt;br /&gt;
			if (getValueOf(&#039;popupPreviewButton&#039;) &amp;amp;&amp;amp; !a.simpleNoMore) {&lt;br /&gt;
				const d = document.createElement(&#039;div&#039;);&lt;br /&gt;
				d.className = &#039;popupPreviewButtonDiv&#039;;&lt;br /&gt;
				const s = document.createElement(&#039;span&#039;);&lt;br /&gt;
				d.appendChild(s);&lt;br /&gt;
				s.className = &#039;popupPreviewButton&#039;;&lt;br /&gt;
				s[&#039;on&#039; + getValueOf(&#039;popupPreviewButtonEvent&#039;)] = function () {&lt;br /&gt;
					a.simpleNoMore = true;&lt;br /&gt;
					d.style.display = &#039;none&#039;;&lt;br /&gt;
					nonsimplePopupContent(a, article);&lt;br /&gt;
				};&lt;br /&gt;
				s.innerHTML = popupString(&#039;show preview&#039;);&lt;br /&gt;
				setPopupHTML(d, &#039;popupPreview&#039;, a.navpopup.idNumber);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (a.navpopup.pending !== 0) {&lt;br /&gt;
			nonsimplePopupContent(a, article);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// simplePopupContent: the content that do not require additional download&lt;br /&gt;
	// (it is shown even when simplePopups is true)&lt;br /&gt;
	function simplePopupContent(a, article) {&lt;br /&gt;
		/* FIXME hack */ a.navpopup.hasPopupMenu = false;&lt;br /&gt;
		a.navpopup.setInnerHTML(popupHTML(a));&lt;br /&gt;
		fillEmptySpans({ navpopup: a.navpopup });&lt;br /&gt;
&lt;br /&gt;
		if (getValueOf(&#039;popupDraggable&#039;)) {&lt;br /&gt;
			let dragHandle = getValueOf(&#039;popupDragHandle&#039;) || null;&lt;br /&gt;
			if (dragHandle &amp;amp;&amp;amp; dragHandle != &#039;all&#039;) {&lt;br /&gt;
				dragHandle += a.navpopup.idNumber;&lt;br /&gt;
			}&lt;br /&gt;
			setTimeout(() =&amp;gt; {&lt;br /&gt;
				a.navpopup.makeDraggable(dragHandle);&lt;br /&gt;
			}, 150);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (getValueOf(&#039;popupRedlinkRemoval&#039;) &amp;amp;&amp;amp; a.className == &#039;new&#039;) {&lt;br /&gt;
			setPopupHTML(&#039;&amp;lt;br&amp;gt;&#039; + popupRedlinkHTML(article), &#039;popupRedlink&#039;, a.navpopup.idNumber);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function debugData(navpopup) {&lt;br /&gt;
		if (getValueOf(&#039;popupDebugging&#039;) &amp;amp;&amp;amp; navpopup.idNumber) {&lt;br /&gt;
			setPopupHTML(&lt;br /&gt;
				&#039;idNumber=&#039; + navpopup.idNumber + &#039;, pending=&#039; + navpopup.pending,&lt;br /&gt;
				&#039;popupError&#039;,&lt;br /&gt;
				navpopup.idNumber&lt;br /&gt;
			);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function newNavpopup(a, article) {&lt;br /&gt;
		const navpopup = new Navpopup();&lt;br /&gt;
		navpopup.fuzz = 5;&lt;br /&gt;
		navpopup.delay = getValueOf(&#039;popupDelay&#039;) * 1000;&lt;br /&gt;
		// increment global counter now&lt;br /&gt;
		navpopup.idNumber = ++pg.idNumber;&lt;br /&gt;
		navpopup.parentAnchor = a;&lt;br /&gt;
		navpopup.parentPopup = a.popData &amp;amp;&amp;amp; a.popData.owner;&lt;br /&gt;
		navpopup.article = article;&lt;br /&gt;
		registerHooks(navpopup);&lt;br /&gt;
		return navpopup;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Should we show nonsimple context?&lt;br /&gt;
	// If simplePopups is set to true, then we do not show nonsimple context,&lt;br /&gt;
	// but if a bottom &amp;quot;show preview&amp;quot; was clicked we do show nonsimple context&lt;br /&gt;
	function shouldShowNonSimple(a) {&lt;br /&gt;
		return !getValueOf(&#039;simplePopups&#039;) || a.simpleNoMore;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Should we show nonsimple context govern by the option (e.g. popupUserInfo)?&lt;br /&gt;
	// If the user explicitly asked for nonsimple context by setting the option to true,&lt;br /&gt;
	// then we show it even in nonsimple mode.&lt;br /&gt;
	function shouldShow(a, option) {&lt;br /&gt;
		if (shouldShowNonSimple(a)) {&lt;br /&gt;
			return getValueOf(option);&lt;br /&gt;
		} else {&lt;br /&gt;
			return typeof window[option] != &#039;undefined&#039; &amp;amp;&amp;amp; window[option];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function nonsimplePopupContent(a, article) {&lt;br /&gt;
		let diff = null,&lt;br /&gt;
			history = null;&lt;br /&gt;
		const params = parseParams(a.href);&lt;br /&gt;
		const oldid = typeof params.oldid == &#039;undefined&#039; ? null : params.oldid;&lt;br /&gt;
		if (shouldShow(a, &#039;popupPreviewDiffs&#039;)) {&lt;br /&gt;
			diff = params.diff;&lt;br /&gt;
		}&lt;br /&gt;
		if (shouldShow(a, &#039;popupPreviewHistory&#039;)) {&lt;br /&gt;
			history = params.action == &#039;history&#039;;&lt;br /&gt;
		}&lt;br /&gt;
		a.navpopup.pending = 0;&lt;br /&gt;
		const referenceElement = footnoteTarget(a);&lt;br /&gt;
		if (referenceElement) {&lt;br /&gt;
			footnotePreview(referenceElement, a.navpopup);&lt;br /&gt;
		} else if (diff || diff === 0) {&lt;br /&gt;
			loadDiff(article, oldid, diff, a.navpopup);&lt;br /&gt;
		} else if (history) {&lt;br /&gt;
			loadAPIPreview(&#039;history&#039;, article, a.navpopup);&lt;br /&gt;
		} else if (shouldShowNonSimple(a) &amp;amp;&amp;amp; pg.re.contribs.test(a.href)) {&lt;br /&gt;
			loadAPIPreview(&#039;contribs&#039;, article, a.navpopup);&lt;br /&gt;
		} else if (shouldShowNonSimple(a) &amp;amp;&amp;amp; pg.re.backlinks.test(a.href)) {&lt;br /&gt;
			loadAPIPreview(&#039;backlinks&#039;, article, a.navpopup);&lt;br /&gt;
		} else if (&lt;br /&gt;
			// FIXME should be able to get all preview combinations with options&lt;br /&gt;
			article.namespaceId() == pg.nsImageId &amp;amp;&amp;amp;&lt;br /&gt;
			(shouldShow(a, &#039;imagePopupsForImages&#039;) || !anchorContainsImage(a))&lt;br /&gt;
		) {&lt;br /&gt;
			loadAPIPreview(&#039;imagepagepreview&#039;, article, a.navpopup);&lt;br /&gt;
			loadImage(article, a.navpopup);&lt;br /&gt;
		} else {&lt;br /&gt;
			if (article.namespaceId() == pg.nsCategoryId &amp;amp;&amp;amp; shouldShow(a, &#039;popupCategoryMembers&#039;)) {&lt;br /&gt;
				loadAPIPreview(&#039;category&#039;, article, a.navpopup);&lt;br /&gt;
			} else if (&lt;br /&gt;
				(article.namespaceId() == pg.nsUserId || article.namespaceId() == pg.nsUsertalkId) &amp;amp;&amp;amp;&lt;br /&gt;
				shouldShow(a, &#039;popupUserInfo&#039;)&lt;br /&gt;
			) {&lt;br /&gt;
				loadAPIPreview(&#039;userinfo&#039;, article, a.navpopup);&lt;br /&gt;
			}&lt;br /&gt;
			if (shouldShowNonSimple(a)) {&lt;br /&gt;
				startArticlePreview(article, oldid, a.navpopup);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function pendingNavpopTask(navpop) {&lt;br /&gt;
		if (navpop &amp;amp;&amp;amp; navpop.pending === null) {&lt;br /&gt;
			navpop.pending = 0;&lt;br /&gt;
		}&lt;br /&gt;
		++navpop.pending;&lt;br /&gt;
		debugData(navpop);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function completedNavpopTask(navpop) {&lt;br /&gt;
		if (navpop &amp;amp;&amp;amp; navpop.pending) {&lt;br /&gt;
			--navpop.pending;&lt;br /&gt;
		}&lt;br /&gt;
		debugData(navpop);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function startArticlePreview(article, oldid, navpop) {&lt;br /&gt;
		navpop.redir = 0;&lt;br /&gt;
		loadPreview(article, oldid, navpop);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function loadPreview(article, oldid, navpop) {&lt;br /&gt;
		if (!navpop.redir) {&lt;br /&gt;
			navpop.originalArticle = article;&lt;br /&gt;
		}&lt;br /&gt;
		article.oldid = oldid;&lt;br /&gt;
		loadAPIPreview(&#039;revision&#039;, article, navpop);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function loadPreviewFromRedir(redirMatch, navpop) {&lt;br /&gt;
		// redirMatch is a regex match&lt;br /&gt;
		const target = new Title().fromWikiText(redirMatch[2]);&lt;br /&gt;
		// overwrite (or add) anchor from original target&lt;br /&gt;
		// mediawiki does overwrite; eg [[User:Lupin/foo3#Done]]&lt;br /&gt;
		if (navpop.article.anchor) {&lt;br /&gt;
			target.anchor = navpop.article.anchor;&lt;br /&gt;
		}&lt;br /&gt;
		navpop.redir++;&lt;br /&gt;
		navpop.redirTarget = target;&lt;br /&gt;
		const warnRedir = redirLink(target, navpop.article);&lt;br /&gt;
		setPopupHTML(warnRedir, &#039;popupWarnRedir&#039;, navpop.idNumber);&lt;br /&gt;
		navpop.article = target;&lt;br /&gt;
		fillEmptySpans({ redir: true, redirTarget: target, navpopup: navpop });&lt;br /&gt;
		return loadPreview(target, null, navpop);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function insertPreview(download) {&lt;br /&gt;
		if (!download.owner) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const redirMatch = pg.re.redirect.exec(download.data);&lt;br /&gt;
		if (download.owner.redir === 0 &amp;amp;&amp;amp; redirMatch) {&lt;br /&gt;
			loadPreviewFromRedir(redirMatch, download.owner);&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (download.owner.visible || !getValueOf(&#039;popupLazyPreviews&#039;)) {&lt;br /&gt;
			insertPreviewNow(download);&lt;br /&gt;
		} else {&lt;br /&gt;
			const id = download.owner.redir ? &#039;PREVIEW_REDIR_HOOK&#039; : &#039;PREVIEW_HOOK&#039;;&lt;br /&gt;
			download.owner.addHook(&lt;br /&gt;
				() =&amp;gt; {&lt;br /&gt;
					insertPreviewNow(download);&lt;br /&gt;
					return true;&lt;br /&gt;
				},&lt;br /&gt;
				&#039;unhide&#039;,&lt;br /&gt;
				&#039;after&#039;,&lt;br /&gt;
				id&lt;br /&gt;
			);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function insertPreviewNow(download) {&lt;br /&gt;
		if (!download.owner) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		const wikiText = download.data;&lt;br /&gt;
		const navpop = download.owner;&lt;br /&gt;
		const art = navpop.redirTarget || navpop.originalArticle;&lt;br /&gt;
&lt;br /&gt;
		makeFixDabs(wikiText, navpop);&lt;br /&gt;
		if (getValueOf(&#039;popupSummaryData&#039;)) {&lt;br /&gt;
			getPageInfo(wikiText, download);&lt;br /&gt;
			setPopupTrailer(getPageInfo(wikiText, download), navpop.idNumber);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		let imagePage = &#039;&#039;;&lt;br /&gt;
		if (art.namespaceId() == pg.nsImageId) {&lt;br /&gt;
			imagePage = art.toString();&lt;br /&gt;
		} else {&lt;br /&gt;
			imagePage = getValidImageFromWikiText(wikiText);&lt;br /&gt;
		}&lt;br /&gt;
		if (imagePage) {&lt;br /&gt;
			loadImage(Title.fromWikiText(imagePage), navpop);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (getValueOf(&#039;popupPreviews&#039;)) {&lt;br /&gt;
			insertArticlePreview(download, art, navpop);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function insertArticlePreview(download, art, navpop) {&lt;br /&gt;
		if (download &amp;amp;&amp;amp; typeof download.data == typeof &#039;&#039;) {&lt;br /&gt;
			if (art.namespaceId() == pg.nsTemplateId &amp;amp;&amp;amp; getValueOf(&#039;popupPreviewRawTemplates&#039;)) {&lt;br /&gt;
				// FIXME compare/consolidate with diff escaping code for wikitext&lt;br /&gt;
				const h =&lt;br /&gt;
					&#039;&amp;lt;hr /&amp;gt;&amp;lt;span style=&amp;quot;font-family: monospace;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
					download.data.entify().split(&#039;\\n&#039;).join(&#039;&amp;lt;br /&amp;gt;\\n&#039;) +&lt;br /&gt;
					&#039;&amp;lt;/span&amp;gt;&#039;;&lt;br /&gt;
				setPopupHTML(h, &#039;popupPreview&#039;, navpop.idNumber);&lt;br /&gt;
			} else {&lt;br /&gt;
				const p = prepPreviewmaker(download.data, art, navpop);&lt;br /&gt;
				p.showPreview();&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function prepPreviewmaker(data, article, navpop) {&lt;br /&gt;
		// deal with tricksy anchors&lt;br /&gt;
		const d = anchorize(data, article.anchorString());&lt;br /&gt;
		const urlBase = joinPath([pg.wiki.articlebase, article.urlString()]);&lt;br /&gt;
		const p = new Previewmaker(d, urlBase, navpop);&lt;br /&gt;
		return p;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Try to imitate the way mediawiki generates HTML anchors from section titles&lt;br /&gt;
	function anchorize(d, anch) {&lt;br /&gt;
		if (!anch) {&lt;br /&gt;
			return d;&lt;br /&gt;
		}&lt;br /&gt;
		const anchRe = RegExp(&lt;br /&gt;
			&#039;(?:=+\\s*&#039; +&lt;br /&gt;
				literalizeRegex(anch).replace(/[_ ]/g, &#039;[_ ]&#039;) +&lt;br /&gt;
				&#039;\\s*=+|\\{\\{\\s*&#039; +&lt;br /&gt;
				getValueOf(&#039;popupAnchorRegexp&#039;) +&lt;br /&gt;
				&#039;\\s*(?:\\|[^|}]*)*?\\s*&#039; +&lt;br /&gt;
				literalizeRegex(anch) +&lt;br /&gt;
				&#039;\\s*(?:\\|[^}]*)?}})&#039;&lt;br /&gt;
		);&lt;br /&gt;
		const match = d.match(anchRe);&lt;br /&gt;
		if (match &amp;amp;&amp;amp; match.length &amp;gt; 0 &amp;amp;&amp;amp; match[0]) {&lt;br /&gt;
			return d.substring(d.indexOf(match[0]));&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// now try to deal with == foo [[bar|baz]] boom == -&amp;gt; #foo_baz_boom&lt;br /&gt;
		const lines = d.split(&#039;\n&#039;);&lt;br /&gt;
		for (let i = 0; i &amp;lt; lines.length; ++i) {&lt;br /&gt;
			lines[i] = lines[i]&lt;br /&gt;
				.replace(/[[]{2}([^|\]]*?[|])?(.*?)[\]]{2}/g, &#039;$2&#039;)&lt;br /&gt;
				.replace(/&#039;&#039;&#039;([^&#039;])/g, &#039;$1&#039;)&lt;br /&gt;
				.replace(/&#039;&#039;([^&#039;])/g, &#039;$1&#039;);&lt;br /&gt;
			if (lines[i].match(anchRe)) {&lt;br /&gt;
				return d.split(&#039;\n&#039;).slice(i).join(&#039;\n&#039;).replace(/^[^=]*/, &#039;&#039;);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return d;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function killPopup() {&lt;br /&gt;
		removeModifierKeyHandler(this);&lt;br /&gt;
		if (getValueOf(&#039;popupShortcutKeys&#039;)) {&lt;br /&gt;
			rmPopupShortcuts();&lt;br /&gt;
		}&lt;br /&gt;
		if (!pg) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (pg.current.link &amp;amp;&amp;amp; pg.current.link.navpopup) {&lt;br /&gt;
			pg.current.link.navpopup.banish();&lt;br /&gt;
		}&lt;br /&gt;
		pg.current.link = null;&lt;br /&gt;
		abortAllDownloads();&lt;br /&gt;
		if (pg.timer.checkPopupPosition) {&lt;br /&gt;
			clearInterval(pg.timer.checkPopupPosition);&lt;br /&gt;
			pg.timer.checkPopupPosition = null;&lt;br /&gt;
		}&lt;br /&gt;
		return true; // preserve default action&lt;br /&gt;
	}&lt;br /&gt;
	// ENDFILE: actions.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: domdrag.js&lt;br /&gt;
	/**&lt;br /&gt;
	 * @file&lt;br /&gt;
	 * The {@link Drag} object, which enables objects to be dragged around.&lt;br /&gt;
	 *&lt;br /&gt;
	 * &amp;lt;pre&amp;gt;&lt;br /&gt;
	 * *************************************************&lt;br /&gt;
	 * dom-drag.js&lt;br /&gt;
	 * 09.25.2001&lt;br /&gt;
	 * www.youngpup.net&lt;br /&gt;
	 * **************************************************&lt;br /&gt;
	 * 10.28.2001 - fixed minor bug where events&lt;br /&gt;
	 * sometimes fired off the handle, not the root.&lt;br /&gt;
	 * *************************************************&lt;br /&gt;
	 * Pared down, some hooks added by [[User:Lupin]]&lt;br /&gt;
	 *&lt;br /&gt;
	 * Copyright Aaron Boodman.&lt;br /&gt;
	 * Saying stupid things daily since March 2001.&lt;br /&gt;
	 * &amp;lt;/pre&amp;gt;&lt;br /&gt;
	 */&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Creates a new Drag object. This is used to make various DOM elements draggable.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @constructor&lt;br /&gt;
	 */&lt;br /&gt;
	function Drag() {&lt;br /&gt;
		/**&lt;br /&gt;
		 * Condition to determine whether or not to drag. This function should take one parameter,&lt;br /&gt;
		 * an Event.  To disable this, set it to &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;.&lt;br /&gt;
		 *&lt;br /&gt;
		 * @type {Function}&lt;br /&gt;
		 */&lt;br /&gt;
		this.startCondition = null;&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
		 * Hook to be run when the drag finishes. This is passed the final coordinates of the&lt;br /&gt;
		 * dragged object (two integers, x and y). To disables this, set it to &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;.&lt;br /&gt;
		 *&lt;br /&gt;
		 * @type {Function}&lt;br /&gt;
		 */&lt;br /&gt;
		this.endHook = null;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Gets an event in a cross-browser manner.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param {Event} e&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Drag.prototype.fixE = function (e) {&lt;br /&gt;
		if (typeof e == &#039;undefined&#039;) {&lt;br /&gt;
			e = window.event;&lt;br /&gt;
		}&lt;br /&gt;
		if (typeof e.layerX == &#039;undefined&#039;) {&lt;br /&gt;
			e.layerX = e.offsetX;&lt;br /&gt;
		}&lt;br /&gt;
		if (typeof e.layerY == &#039;undefined&#039;) {&lt;br /&gt;
			e.layerY = e.offsetY;&lt;br /&gt;
		}&lt;br /&gt;
		return e;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Initialises the Drag instance by telling it which object you want to be draggable, and what&lt;br /&gt;
	 * you want to drag it by.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param {HTMLElement} o The &amp;quot;handle&amp;quot; by which &amp;lt;code&amp;gt;oRoot&amp;lt;/code&amp;gt; is dragged.&lt;br /&gt;
	 * @param {HTMLElement} oRoot The object which moves when &amp;lt;code&amp;gt;o&amp;lt;/code&amp;gt; is dragged, or &amp;lt;code&amp;gt;o&amp;lt;/code&amp;gt; if omitted.&lt;br /&gt;
	 */&lt;br /&gt;
	Drag.prototype.init = function (o, oRoot) {&lt;br /&gt;
		const dragObj = this;&lt;br /&gt;
		this.obj = o;&lt;br /&gt;
		o.onmousedown = function (e) {&lt;br /&gt;
			dragObj.start.apply(dragObj, [e]);&lt;br /&gt;
		};&lt;br /&gt;
		o.dragging = false;&lt;br /&gt;
		o.popups_draggable = true;&lt;br /&gt;
		o.hmode = true;&lt;br /&gt;
		o.vmode = true;&lt;br /&gt;
&lt;br /&gt;
		o.root = oRoot || o;&lt;br /&gt;
&lt;br /&gt;
		if (isNaN(parseInt(o.root.style.left, 10))) {&lt;br /&gt;
			o.root.style.left = &#039;0px&#039;;&lt;br /&gt;
		}&lt;br /&gt;
		if (isNaN(parseInt(o.root.style.top, 10))) {&lt;br /&gt;
			o.root.style.top = &#039;0px&#039;;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		o.root.onthisStart = function () {};&lt;br /&gt;
		o.root.onthisEnd = function () {};&lt;br /&gt;
		o.root.onthis = function () {};&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Starts the drag.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @private&lt;br /&gt;
	 * @param {Event} e&lt;br /&gt;
	 */&lt;br /&gt;
	Drag.prototype.start = function (e) {&lt;br /&gt;
		const o = this.obj; // = this;&lt;br /&gt;
		e = this.fixE(e);&lt;br /&gt;
		if (this.startCondition &amp;amp;&amp;amp; !this.startCondition(e)) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		const y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom, 10);&lt;br /&gt;
		const x = parseInt(o.hmode ? o.root.style.left : o.root.style.right, 10);&lt;br /&gt;
		o.root.onthisStart(x, y);&lt;br /&gt;
&lt;br /&gt;
		o.lastMouseX = e.clientX;&lt;br /&gt;
		o.lastMouseY = e.clientY;&lt;br /&gt;
&lt;br /&gt;
		const dragObj = this;&lt;br /&gt;
		o.onmousemoveDefault = document.onmousemove;&lt;br /&gt;
		o.dragging = true;&lt;br /&gt;
		document.onmousemove = function (e) {&lt;br /&gt;
			dragObj.drag.apply(dragObj, [e]);&lt;br /&gt;
		};&lt;br /&gt;
		document.onmouseup = function (e) {&lt;br /&gt;
			dragObj.end.apply(dragObj, [e]);&lt;br /&gt;
		};&lt;br /&gt;
		return false;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Does the drag.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param {Event} e&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Drag.prototype.drag = function (e) {&lt;br /&gt;
		e = this.fixE(e);&lt;br /&gt;
		const o = this.obj;&lt;br /&gt;
&lt;br /&gt;
		const ey = e.clientY;&lt;br /&gt;
		const ex = e.clientX;&lt;br /&gt;
		const y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom, 10);&lt;br /&gt;
		const x = parseInt(o.hmode ? o.root.style.left : o.root.style.right, 10);&lt;br /&gt;
		let nx, ny;&lt;br /&gt;
&lt;br /&gt;
		nx = x + (ex - o.lastMouseX) * (o.hmode ? 1 : -1);&lt;br /&gt;
		ny = y + (ey - o.lastMouseY) * (o.vmode ? 1 : -1);&lt;br /&gt;
&lt;br /&gt;
		this.obj.root.style[o.hmode ? &#039;left&#039; : &#039;right&#039;] = nx + &#039;px&#039;;&lt;br /&gt;
		this.obj.root.style[o.vmode ? &#039;top&#039; : &#039;bottom&#039;] = ny + &#039;px&#039;;&lt;br /&gt;
		this.obj.lastMouseX = ex;&lt;br /&gt;
		this.obj.lastMouseY = ey;&lt;br /&gt;
&lt;br /&gt;
		this.obj.root.onthis(nx, ny);&lt;br /&gt;
		return false;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Ends the drag.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Drag.prototype.end = function () {&lt;br /&gt;
		document.onmousemove = this.obj.onmousemoveDefault;&lt;br /&gt;
		document.onmouseup = null;&lt;br /&gt;
		this.obj.dragging = false;&lt;br /&gt;
		if (this.endHook) {&lt;br /&gt;
			this.endHook(&lt;br /&gt;
				parseInt(this.obj.root.style[this.obj.hmode ? &#039;left&#039; : &#039;right&#039;], 10),&lt;br /&gt;
				parseInt(this.obj.root.style[this.obj.vmode ? &#039;top&#039; : &#039;bottom&#039;], 10)&lt;br /&gt;
			);&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
	// ENDFILE: domdrag.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: structures.js&lt;br /&gt;
	pg.structures.original = {};&lt;br /&gt;
	pg.structures.original.popupLayout = function () {&lt;br /&gt;
		return [&lt;br /&gt;
			&#039;popupError&#039;,&lt;br /&gt;
			&#039;popupImage&#039;,&lt;br /&gt;
			&#039;popupTopLinks&#039;,&lt;br /&gt;
			&#039;popupTitle&#039;,&lt;br /&gt;
			&#039;popupUserData&#039;,&lt;br /&gt;
			&#039;popupData&#039;,&lt;br /&gt;
			&#039;popupOtherLinks&#039;,&lt;br /&gt;
			&#039;popupRedir&#039;,&lt;br /&gt;
			[&lt;br /&gt;
				&#039;popupWarnRedir&#039;,&lt;br /&gt;
				&#039;popupRedirTopLinks&#039;,&lt;br /&gt;
				&#039;popupRedirTitle&#039;,&lt;br /&gt;
				&#039;popupRedirData&#039;,&lt;br /&gt;
				&#039;popupRedirOtherLinks&#039;,&lt;br /&gt;
			],&lt;br /&gt;
			&#039;popupMiscTools&#039;,&lt;br /&gt;
			[&#039;popupRedlink&#039;],&lt;br /&gt;
			&#039;popupPrePreviewSep&#039;,&lt;br /&gt;
			&#039;popupPreview&#039;,&lt;br /&gt;
			&#039;popupSecondPreview&#039;,&lt;br /&gt;
			&#039;popupPreviewMore&#039;,&lt;br /&gt;
			&#039;popupPostPreview&#039;,&lt;br /&gt;
			&#039;popupFixDab&#039;,&lt;br /&gt;
		];&lt;br /&gt;
	};&lt;br /&gt;
	pg.structures.original.popupRedirSpans = function () {&lt;br /&gt;
		return [&lt;br /&gt;
			&#039;popupRedir&#039;,&lt;br /&gt;
			&#039;popupWarnRedir&#039;,&lt;br /&gt;
			&#039;popupRedirTopLinks&#039;,&lt;br /&gt;
			&#039;popupRedirTitle&#039;,&lt;br /&gt;
			&#039;popupRedirData&#039;,&lt;br /&gt;
			&#039;popupRedirOtherLinks&#039;,&lt;br /&gt;
		];&lt;br /&gt;
	};&lt;br /&gt;
	pg.structures.original.popupTitle = function (x) {&lt;br /&gt;
		log(&#039;defaultstructure.popupTitle&#039;);&lt;br /&gt;
		if (!getValueOf(&#039;popupNavLinks&#039;)) {&lt;br /&gt;
			return navlinkStringToHTML(&#039;&amp;lt;b&amp;gt;&amp;lt;&amp;lt;mainlink&amp;gt;&amp;gt;&amp;lt;/b&amp;gt;&#039;, x.article, x.params);&lt;br /&gt;
		}&lt;br /&gt;
		return &#039;&#039;;&lt;br /&gt;
	};&lt;br /&gt;
	pg.structures.original.popupTopLinks = function (x) {&lt;br /&gt;
		log(&#039;defaultstructure.popupTopLinks&#039;);&lt;br /&gt;
		if (getValueOf(&#039;popupNavLinks&#039;)) {&lt;br /&gt;
			return navLinksHTML(x.article, x.hint, x.params);&lt;br /&gt;
		}&lt;br /&gt;
		return &#039;&#039;;&lt;br /&gt;
	};&lt;br /&gt;
	pg.structures.original.popupImage = function (x) {&lt;br /&gt;
		log(&#039;original.popupImage, x.article=&#039; + x.article + &#039;, x.navpop.idNumber=&#039; + x.navpop.idNumber);&lt;br /&gt;
		return imageHTML(x.article, x.navpop.idNumber);&lt;br /&gt;
	};&lt;br /&gt;
	pg.structures.original.popupRedirTitle = pg.structures.original.popupTitle;&lt;br /&gt;
	pg.structures.original.popupRedirTopLinks = pg.structures.original.popupTopLinks;&lt;br /&gt;
&lt;br /&gt;
	function copyStructure(oldStructure, newStructure) {&lt;br /&gt;
		pg.structures[newStructure] = {};&lt;br /&gt;
		for (const prop in pg.structures[oldStructure]) {&lt;br /&gt;
			pg.structures[newStructure][prop] = pg.structures[oldStructure][prop];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	copyStructure(&#039;original&#039;, &#039;nostalgia&#039;);&lt;br /&gt;
	pg.structures.nostalgia.popupTopLinks = function (x) {&lt;br /&gt;
		let str = &#039;&#039;;&lt;br /&gt;
		str += &#039;&amp;lt;b&amp;gt;&amp;lt;&amp;lt;mainlink|shortcut= &amp;gt;&amp;gt;&amp;lt;/b&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
		// user links&lt;br /&gt;
		// contribs - log - count - email - block&lt;br /&gt;
		// count only if applicable; block only if popupAdminLinks&lt;br /&gt;
		str += &#039;if(user){&amp;lt;br&amp;gt;&amp;lt;&amp;lt;contribs|shortcut=c&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
		str += &#039;if(wikimedia){*&amp;lt;&amp;lt;count|shortcut=#&amp;gt;&amp;gt;}&#039;;&lt;br /&gt;
		str += &#039;if(ipuser){}else{*&amp;lt;&amp;lt;email|shortcut=E&amp;gt;&amp;gt;}if(admin){*&amp;lt;&amp;lt;block|shortcut=b&amp;gt;&amp;gt;}}&#039;;&lt;br /&gt;
&lt;br /&gt;
		// editing links&lt;br /&gt;
		// talkpage   -&amp;gt; edit|new - history - un|watch - article|edit&lt;br /&gt;
		// other page -&amp;gt; edit - history - un|watch - talk|edit|new&lt;br /&gt;
		const editstr = &#039;&amp;lt;&amp;lt;edit|shortcut=e&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
		const editOldidStr =&lt;br /&gt;
			&#039;if(oldid){&amp;lt;&amp;lt;editOld|shortcut=e&amp;gt;&amp;gt;|&amp;lt;&amp;lt;revert|shortcut=v|rv&amp;gt;&amp;gt;|&amp;lt;&amp;lt;edit|cur&amp;gt;&amp;gt;}else{&#039; +&lt;br /&gt;
			editstr +&lt;br /&gt;
			&#039;}&#039;;&lt;br /&gt;
		const historystr = &#039;&amp;lt;&amp;lt;history|shortcut=h&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
		const watchstr = &#039;&amp;lt;&amp;lt;unwatch|unwatchShort&amp;gt;&amp;gt;|&amp;lt;&amp;lt;watch|shortcut=w|watchThingy&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
		str +=&lt;br /&gt;
			&#039;&amp;lt;br&amp;gt;if(talk){&#039; +&lt;br /&gt;
			editOldidStr +&lt;br /&gt;
			&#039;|&amp;lt;&amp;lt;new|shortcut=+&amp;gt;&amp;gt;&#039; +&lt;br /&gt;
			&#039;*&#039; +&lt;br /&gt;
			historystr +&lt;br /&gt;
			&#039;*&#039; +&lt;br /&gt;
			watchstr +&lt;br /&gt;
			&#039;*&#039; +&lt;br /&gt;
			&#039;&amp;lt;b&amp;gt;&amp;lt;&amp;lt;article|shortcut=a&amp;gt;&amp;gt;&amp;lt;/b&amp;gt;|&amp;lt;&amp;lt;editArticle|edit&amp;gt;&amp;gt;&#039; +&lt;br /&gt;
			&#039;}else{&#039; + // not a talk page&lt;br /&gt;
			editOldidStr +&lt;br /&gt;
			&#039;*&#039; +&lt;br /&gt;
			historystr +&lt;br /&gt;
			&#039;*&#039; +&lt;br /&gt;
			watchstr +&lt;br /&gt;
			&#039;*&#039; +&lt;br /&gt;
			&#039;&amp;lt;b&amp;gt;&amp;lt;&amp;lt;talk|shortcut=t&amp;gt;&amp;gt;&amp;lt;/b&amp;gt;|&amp;lt;&amp;lt;editTalk|edit&amp;gt;&amp;gt;|&amp;lt;&amp;lt;newTalk|shortcut=+|new&amp;gt;&amp;gt;}&#039;;&lt;br /&gt;
&lt;br /&gt;
		// misc links&lt;br /&gt;
		str += &#039;&amp;lt;br&amp;gt;&amp;lt;&amp;lt;whatLinksHere|shortcut=l&amp;gt;&amp;gt;*&amp;lt;&amp;lt;relatedChanges|shortcut=r&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
		str += &#039;if(admin){&amp;lt;br&amp;gt;}else{*}&amp;lt;&amp;lt;move|shortcut=m&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
		// admin links&lt;br /&gt;
		str +=&lt;br /&gt;
			&#039;if(admin){*&amp;lt;&amp;lt;unprotect|unprotectShort&amp;gt;&amp;gt;|&amp;lt;&amp;lt;protect|shortcut=p&amp;gt;&amp;gt;*&#039; +&lt;br /&gt;
			&#039;&amp;lt;&amp;lt;undelete|undeleteShort&amp;gt;&amp;gt;|&amp;lt;&amp;lt;delete|shortcut=d&amp;gt;&amp;gt;}&#039;;&lt;br /&gt;
		return navlinkStringToHTML(str, x.article, x.params);&lt;br /&gt;
	};&lt;br /&gt;
	pg.structures.nostalgia.popupRedirTopLinks = pg.structures.nostalgia.popupTopLinks;&lt;br /&gt;
&lt;br /&gt;
	/** -- fancy -- */&lt;br /&gt;
	copyStructure(&#039;original&#039;, &#039;fancy&#039;);&lt;br /&gt;
	pg.structures.fancy.popupTitle = function (x) {&lt;br /&gt;
		return navlinkStringToHTML(&#039;&amp;lt;font size=+0&amp;gt;&amp;lt;&amp;lt;mainlink&amp;gt;&amp;gt;&amp;lt;/font&amp;gt;&#039;, x.article, x.params);&lt;br /&gt;
	};&lt;br /&gt;
	pg.structures.fancy.popupTopLinks = function (x) {&lt;br /&gt;
		const hist =&lt;br /&gt;
			&#039;&amp;lt;&amp;lt;history|shortcut=h|hist&amp;gt;&amp;gt;|&amp;lt;&amp;lt;lastEdit|shortcut=/|last&amp;gt;&amp;gt;|&amp;lt;&amp;lt;editors|shortcut=E|eds&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
		const watch = &#039;&amp;lt;&amp;lt;unwatch|unwatchShort&amp;gt;&amp;gt;|&amp;lt;&amp;lt;watch|shortcut=w|watchThingy&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
		const move = &#039;&amp;lt;&amp;lt;move|shortcut=m|move&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
		return navlinkStringToHTML(&lt;br /&gt;
			&#039;if(talk){&#039; +&lt;br /&gt;
				&#039;&amp;lt;&amp;lt;edit|shortcut=e&amp;gt;&amp;gt;|&amp;lt;&amp;lt;new|shortcut=+|+&amp;gt;&amp;gt;*&#039; +&lt;br /&gt;
				hist +&lt;br /&gt;
				&#039;*&#039; +&lt;br /&gt;
				&#039;&amp;lt;&amp;lt;article|shortcut=a&amp;gt;&amp;gt;|&amp;lt;&amp;lt;editArticle|edit&amp;gt;&amp;gt;&#039; +&lt;br /&gt;
				&#039;*&#039; +&lt;br /&gt;
				watch +&lt;br /&gt;
				&#039;*&#039; +&lt;br /&gt;
				move +&lt;br /&gt;
				&#039;}else{&amp;lt;&amp;lt;edit|shortcut=e&amp;gt;&amp;gt;*&#039; +&lt;br /&gt;
				hist +&lt;br /&gt;
				&#039;*&amp;lt;&amp;lt;talk|shortcut=t|&amp;gt;&amp;gt;|&amp;lt;&amp;lt;editTalk|edit&amp;gt;&amp;gt;|&amp;lt;&amp;lt;newTalk|shortcut=+|new&amp;gt;&amp;gt;&#039; +&lt;br /&gt;
				&#039;*&#039; +&lt;br /&gt;
				watch +&lt;br /&gt;
				&#039;*&#039; +&lt;br /&gt;
				move +&lt;br /&gt;
				&#039;}&amp;lt;br&amp;gt;&#039;,&lt;br /&gt;
			x.article,&lt;br /&gt;
			x.params&lt;br /&gt;
		);&lt;br /&gt;
	};&lt;br /&gt;
	pg.structures.fancy.popupOtherLinks = function (x) {&lt;br /&gt;
		const admin =&lt;br /&gt;
			&#039;&amp;lt;&amp;lt;unprotect|unprotectShort&amp;gt;&amp;gt;|&amp;lt;&amp;lt;protect|shortcut=p&amp;gt;&amp;gt;*&amp;lt;&amp;lt;undelete|undeleteShort&amp;gt;&amp;gt;|&amp;lt;&amp;lt;delete|shortcut=d|del&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
		let user = &#039;&amp;lt;&amp;lt;contribs|shortcut=c&amp;gt;&amp;gt;if(wikimedia){|&amp;lt;&amp;lt;count|shortcut=#|#&amp;gt;&amp;gt;}&#039;;&lt;br /&gt;
		user +=&lt;br /&gt;
			&#039;if(ipuser){|&amp;lt;&amp;lt;arin&amp;gt;&amp;gt;}else{*&amp;lt;&amp;lt;email|shortcut=E|&#039; +&lt;br /&gt;
			popupString(&#039;email&#039;) +&lt;br /&gt;
			&#039;&amp;gt;&amp;gt;}if(admin){*&amp;lt;&amp;lt;block|shortcut=b&amp;gt;&amp;gt;}&#039;;&lt;br /&gt;
&lt;br /&gt;
		const normal = &#039;&amp;lt;&amp;lt;whatLinksHere|shortcut=l|links here&amp;gt;&amp;gt;*&amp;lt;&amp;lt;relatedChanges|shortcut=r|related&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
		return navlinkStringToHTML(&lt;br /&gt;
			&#039;&amp;lt;br&amp;gt;if(user){&#039; + user + &#039;*}if(admin){&#039; + admin + &#039;if(user){&amp;lt;br&amp;gt;}else{*}}&#039; + normal,&lt;br /&gt;
			x.article,&lt;br /&gt;
			x.params&lt;br /&gt;
		);&lt;br /&gt;
	};&lt;br /&gt;
	pg.structures.fancy.popupRedirTitle = pg.structures.fancy.popupTitle;&lt;br /&gt;
	pg.structures.fancy.popupRedirTopLinks = pg.structures.fancy.popupTopLinks;&lt;br /&gt;
	pg.structures.fancy.popupRedirOtherLinks = pg.structures.fancy.popupOtherLinks;&lt;br /&gt;
&lt;br /&gt;
	/** -- fancy2 -- */&lt;br /&gt;
	// hack for [[User:MacGyverMagic]]&lt;br /&gt;
	copyStructure(&#039;fancy&#039;, &#039;fancy2&#039;);&lt;br /&gt;
	pg.structures.fancy2.popupTopLinks = function (x) {&lt;br /&gt;
		// hack out the &amp;lt;br&amp;gt; at the end and put one at the beginning&lt;br /&gt;
		return &#039;&amp;lt;br&amp;gt;&#039; + pg.structures.fancy.popupTopLinks(x).replace(/&amp;lt;br&amp;gt;$/i, &#039;&#039;);&lt;br /&gt;
	};&lt;br /&gt;
	pg.structures.fancy2.popupLayout = function () {&lt;br /&gt;
		// move toplinks to after the title&lt;br /&gt;
		return [&lt;br /&gt;
			&#039;popupError&#039;,&lt;br /&gt;
			&#039;popupImage&#039;,&lt;br /&gt;
			&#039;popupTitle&#039;,&lt;br /&gt;
			&#039;popupUserData&#039;,&lt;br /&gt;
			&#039;popupData&#039;,&lt;br /&gt;
			&#039;popupTopLinks&#039;,&lt;br /&gt;
			&#039;popupOtherLinks&#039;,&lt;br /&gt;
			&#039;popupRedir&#039;,&lt;br /&gt;
			[&lt;br /&gt;
				&#039;popupWarnRedir&#039;,&lt;br /&gt;
				&#039;popupRedirTopLinks&#039;,&lt;br /&gt;
				&#039;popupRedirTitle&#039;,&lt;br /&gt;
				&#039;popupRedirData&#039;,&lt;br /&gt;
				&#039;popupRedirOtherLinks&#039;,&lt;br /&gt;
			],&lt;br /&gt;
			&#039;popupMiscTools&#039;,&lt;br /&gt;
			[&#039;popupRedlink&#039;],&lt;br /&gt;
			&#039;popupPrePreviewSep&#039;,&lt;br /&gt;
			&#039;popupPreview&#039;,&lt;br /&gt;
			&#039;popupSecondPreview&#039;,&lt;br /&gt;
			&#039;popupPreviewMore&#039;,&lt;br /&gt;
			&#039;popupPostPreview&#039;,&lt;br /&gt;
			&#039;popupFixDab&#039;,&lt;br /&gt;
		];&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/** -- menus -- */&lt;br /&gt;
	copyStructure(&#039;original&#039;, &#039;menus&#039;);&lt;br /&gt;
	pg.structures.menus.popupLayout = function () {&lt;br /&gt;
		return [&lt;br /&gt;
			&#039;popupError&#039;,&lt;br /&gt;
			&#039;popupImage&#039;,&lt;br /&gt;
			&#039;popupTopLinks&#039;,&lt;br /&gt;
			&#039;popupTitle&#039;,&lt;br /&gt;
			&#039;popupOtherLinks&#039;,&lt;br /&gt;
			&#039;popupRedir&#039;,&lt;br /&gt;
			[&lt;br /&gt;
				&#039;popupWarnRedir&#039;,&lt;br /&gt;
				&#039;popupRedirTopLinks&#039;,&lt;br /&gt;
				&#039;popupRedirTitle&#039;,&lt;br /&gt;
				&#039;popupRedirData&#039;,&lt;br /&gt;
				&#039;popupRedirOtherLinks&#039;,&lt;br /&gt;
			],&lt;br /&gt;
			&#039;popupUserData&#039;,&lt;br /&gt;
			&#039;popupData&#039;,&lt;br /&gt;
			&#039;popupMiscTools&#039;,&lt;br /&gt;
			[&#039;popupRedlink&#039;],&lt;br /&gt;
			&#039;popupPrePreviewSep&#039;,&lt;br /&gt;
			&#039;popupPreview&#039;,&lt;br /&gt;
			&#039;popupSecondPreview&#039;,&lt;br /&gt;
			&#039;popupPreviewMore&#039;,&lt;br /&gt;
			&#039;popupPostPreview&#039;,&lt;br /&gt;
			&#039;popupFixDab&#039;,&lt;br /&gt;
		];&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	pg.structures.menus.popupTopLinks = function (x, shorter) {&lt;br /&gt;
		// FIXME maybe this stuff should be cached&lt;br /&gt;
		const s = [];&lt;br /&gt;
		const dropclass = &#039;popup_drop&#039;;&lt;br /&gt;
		const enddiv = &#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
		let hist = &#039;&amp;lt;&amp;lt;history|shortcut=h&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
		if (!shorter) {&lt;br /&gt;
			hist = &#039;&amp;lt;menurow&amp;gt;&#039; + hist + &#039;|&amp;lt;&amp;lt;historyfeed|rss&amp;gt;&amp;gt;|&amp;lt;&amp;lt;editors|shortcut=E&amp;gt;&amp;gt;&amp;lt;/menurow&amp;gt;&#039;;&lt;br /&gt;
		}&lt;br /&gt;
		const lastedit = &#039;&amp;lt;&amp;lt;lastEdit|shortcut=/|show last edit&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
		const thank = &#039;if(diff){&amp;lt;&amp;lt;thank|send thanks&amp;gt;&amp;gt;}&#039;;&lt;br /&gt;
		const jsHistory = &#039;&amp;lt;&amp;lt;lastContrib|last set of edits&amp;gt;&amp;gt;&amp;lt;&amp;lt;sinceMe|changes since mine&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
		const linkshere = &#039;&amp;lt;&amp;lt;whatLinksHere|shortcut=l|what links here&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
		const related = &#039;&amp;lt;&amp;lt;relatedChanges|shortcut=r|related changes&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
		const search =&lt;br /&gt;
			&#039;&amp;lt;menurow&amp;gt;&amp;lt;&amp;lt;search|shortcut=s&amp;gt;&amp;gt;if(wikimedia){|&amp;lt;&amp;lt;globalsearch|shortcut=g|global&amp;gt;&amp;gt;}&#039; +&lt;br /&gt;
			&#039;|&amp;lt;&amp;lt;google|shortcut=G|web&amp;gt;&amp;gt;&amp;lt;/menurow&amp;gt;&#039;;&lt;br /&gt;
		const watch = &#039;&amp;lt;menurow&amp;gt;&amp;lt;&amp;lt;unwatch|unwatchShort&amp;gt;&amp;gt;|&amp;lt;&amp;lt;watch|shortcut=w|watchThingy&amp;gt;&amp;gt;&amp;lt;/menurow&amp;gt;&#039;;&lt;br /&gt;
		const protect =&lt;br /&gt;
			&#039;&amp;lt;menurow&amp;gt;&amp;lt;&amp;lt;unprotect|unprotectShort&amp;gt;&amp;gt;|&#039; +&lt;br /&gt;
			&#039;&amp;lt;&amp;lt;protect|shortcut=p&amp;gt;&amp;gt;|&amp;lt;&amp;lt;protectlog|log&amp;gt;&amp;gt;&amp;lt;/menurow&amp;gt;&#039;;&lt;br /&gt;
		const del =&lt;br /&gt;
			&#039;&amp;lt;menurow&amp;gt;&amp;lt;&amp;lt;undelete|undeleteShort&amp;gt;&amp;gt;|&amp;lt;&amp;lt;delete|shortcut=d&amp;gt;&amp;gt;|&amp;lt;&amp;lt;deletelog|log&amp;gt;&amp;gt;&amp;lt;/menurow&amp;gt;&#039;;&lt;br /&gt;
		const move = &#039;&amp;lt;&amp;lt;move|shortcut=m|move page&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
		const nullPurge = &#039;&amp;lt;menurow&amp;gt;&amp;lt;&amp;lt;nullEdit|shortcut=n|null edit&amp;gt;&amp;gt;|&amp;lt;&amp;lt;purge|shortcut=P&amp;gt;&amp;gt;&amp;lt;/menurow&amp;gt;&#039;;&lt;br /&gt;
		const viewOptions = &#039;&amp;lt;menurow&amp;gt;&amp;lt;&amp;lt;view|shortcut=v&amp;gt;&amp;gt;|&amp;lt;&amp;lt;render|shortcut=S&amp;gt;&amp;gt;|&amp;lt;&amp;lt;raw&amp;gt;&amp;gt;&amp;lt;/menurow&amp;gt;&#039;;&lt;br /&gt;
		const editRow =&lt;br /&gt;
			&#039;if(oldid){&#039; +&lt;br /&gt;
			&#039;&amp;lt;menurow&amp;gt;&amp;lt;&amp;lt;edit|shortcut=e&amp;gt;&amp;gt;|&amp;lt;&amp;lt;editOld|shortcut=e|this&amp;amp;nbsp;revision&amp;gt;&amp;gt;&amp;lt;/menurow&amp;gt;&#039; +&lt;br /&gt;
			&#039;&amp;lt;menurow&amp;gt;&amp;lt;&amp;lt;revert|shortcut=v&amp;gt;&amp;gt;|&amp;lt;&amp;lt;undo&amp;gt;&amp;gt;&amp;lt;/menurow&amp;gt;&#039; +&lt;br /&gt;
			&#039;}else{&amp;lt;&amp;lt;edit|shortcut=e&amp;gt;&amp;gt;}&#039;;&lt;br /&gt;
		const markPatrolled = &#039;if(rcid){&amp;lt;&amp;lt;markpatrolled|mark patrolled&amp;gt;&amp;gt;}&#039;;&lt;br /&gt;
		const newTopic = &#039;if(talk){&amp;lt;&amp;lt;new|shortcut=+|new topic&amp;gt;&amp;gt;}&#039;;&lt;br /&gt;
		const protectDelete = &#039;if(admin){&#039; + protect + del + &#039;}&#039;;&lt;br /&gt;
&lt;br /&gt;
		if (getValueOf(&#039;popupActionsMenu&#039;)) {&lt;br /&gt;
			s.push(&#039;&amp;lt;&amp;lt;mainlink&amp;gt;&amp;gt;*&#039; + menuTitle(dropclass, &#039;actions&#039;));&lt;br /&gt;
		} else {&lt;br /&gt;
			s.push(&#039;&amp;lt;div class=&amp;quot;&#039; + dropclass + &#039;&amp;quot;&amp;gt;&amp;lt;&amp;lt;mainlink&amp;gt;&amp;gt;&#039;);&lt;br /&gt;
		}&lt;br /&gt;
		s.push(&#039;&amp;lt;menu&amp;gt;&#039;);&lt;br /&gt;
		s.push(editRow + markPatrolled + newTopic + hist + lastedit + thank);&lt;br /&gt;
		if (!shorter) {&lt;br /&gt;
			s.push(jsHistory);&lt;br /&gt;
		}&lt;br /&gt;
		s.push(move + linkshere + related);&lt;br /&gt;
		if (!shorter) {&lt;br /&gt;
			s.push(nullPurge + search);&lt;br /&gt;
		}&lt;br /&gt;
		if (!shorter) {&lt;br /&gt;
			s.push(viewOptions);&lt;br /&gt;
		}&lt;br /&gt;
		s.push(&#039;&amp;lt;hr /&amp;gt;&#039; + watch + protectDelete);&lt;br /&gt;
		s.push(&lt;br /&gt;
			&#039;&amp;lt;hr /&amp;gt;&#039; +&lt;br /&gt;
				&#039;if(talk){&amp;lt;&amp;lt;article|shortcut=a|view article&amp;gt;&amp;gt;&amp;lt;&amp;lt;editArticle|edit article&amp;gt;&amp;gt;}&#039; +&lt;br /&gt;
				&#039;else{&amp;lt;&amp;lt;talk|shortcut=t|talk page&amp;gt;&amp;gt;&amp;lt;&amp;lt;editTalk|edit talk&amp;gt;&amp;gt;&#039; +&lt;br /&gt;
				&#039;&amp;lt;&amp;lt;newTalk|shortcut=+|new topic&amp;gt;&amp;gt;}&amp;lt;/menu&amp;gt;&#039; +&lt;br /&gt;
				enddiv&lt;br /&gt;
		);&lt;br /&gt;
&lt;br /&gt;
		// user menu starts here&lt;br /&gt;
		const email = &#039;&amp;lt;&amp;lt;email|shortcut=E|email user&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
		const contribs =&lt;br /&gt;
			&#039;if(wikimedia){&amp;lt;menurow&amp;gt;}&amp;lt;&amp;lt;contribs|shortcut=c|contributions&amp;gt;&amp;gt;if(wikimedia){&amp;lt;/menurow&amp;gt;}&#039; +&lt;br /&gt;
			&#039;if(admin){&amp;lt;menurow&amp;gt;&amp;lt;&amp;lt;deletedContribs&amp;gt;&amp;gt;&amp;lt;/menurow&amp;gt;}&#039;;&lt;br /&gt;
&lt;br /&gt;
		s.push(&#039;if(user){*&#039; + menuTitle(dropclass, &#039;user&#039;));&lt;br /&gt;
		s.push(&#039;&amp;lt;menu&amp;gt;&#039;);&lt;br /&gt;
		s.push(&#039;&amp;lt;menurow&amp;gt;&amp;lt;&amp;lt;userPage|shortcut=u|user&amp;amp;nbsp;page&amp;gt;&amp;gt;|&amp;lt;&amp;lt;userSpace|space&amp;gt;&amp;gt;&amp;lt;/menurow&amp;gt;&#039;);&lt;br /&gt;
		s.push(&lt;br /&gt;
			&#039;&amp;lt;&amp;lt;userTalk|shortcut=t|user talk&amp;gt;&amp;gt;&amp;lt;&amp;lt;editUserTalk|edit user talk&amp;gt;&amp;gt;&#039; +&lt;br /&gt;
				&#039;&amp;lt;&amp;lt;newUserTalk|shortcut=+|leave comment&amp;gt;&amp;gt;&#039;&lt;br /&gt;
		);&lt;br /&gt;
		if (!shorter) {&lt;br /&gt;
			s.push(&#039;if(ipuser){&amp;lt;&amp;lt;arin&amp;gt;&amp;gt;}else{&#039; + email + &#039;}&#039;);&lt;br /&gt;
		} else {&lt;br /&gt;
			s.push(&#039;if(ipuser){}else{&#039; + email + &#039;}&#039;);&lt;br /&gt;
		}&lt;br /&gt;
		s.push(&#039;&amp;lt;hr /&amp;gt;&#039; + contribs + &#039;&amp;lt;&amp;lt;userlog|shortcut=L|user log&amp;gt;&amp;gt;&#039;);&lt;br /&gt;
		s.push(&#039;if(wikimedia){&amp;lt;&amp;lt;count|shortcut=#|edit counter&amp;gt;&amp;gt;}&#039;);&lt;br /&gt;
		s.push(&lt;br /&gt;
			&#039;if(admin){&amp;lt;menurow&amp;gt;&amp;lt;&amp;lt;unblock|unblockShort&amp;gt;&amp;gt;|&amp;lt;&amp;lt;block|shortcut=b|block user&amp;gt;&amp;gt;&amp;lt;/menurow&amp;gt;}&#039;&lt;br /&gt;
		);&lt;br /&gt;
		s.push(&#039;&amp;lt;&amp;lt;blocklog|shortcut=B|block log&amp;gt;&amp;gt;&#039;);&lt;br /&gt;
		s.push(&#039;&amp;lt;/menu&amp;gt;&#039; + enddiv + &#039;}&#039;);&lt;br /&gt;
&lt;br /&gt;
		// popups menu starts here&lt;br /&gt;
		if (getValueOf(&#039;popupSetupMenu&#039;) &amp;amp;&amp;amp; !x.navpop.hasPopupMenu /* FIXME: hack */) {&lt;br /&gt;
			x.navpop.hasPopupMenu = true;&lt;br /&gt;
			s.push(&#039;*&#039; + menuTitle(dropclass, &#039;popupsMenu&#039;) + &#039;&amp;lt;menu&amp;gt;&#039;);&lt;br /&gt;
			s.push(&#039;&amp;lt;&amp;lt;togglePreviews|toggle previews&amp;gt;&amp;gt;&#039;);&lt;br /&gt;
			s.push(&#039;&amp;lt;&amp;lt;purgePopups|reset&amp;gt;&amp;gt;&#039;);&lt;br /&gt;
			s.push(&#039;&amp;lt;&amp;lt;disablePopups|disable&amp;gt;&amp;gt;&#039;);&lt;br /&gt;
			s.push(&#039;&amp;lt;/menu&amp;gt;&#039; + enddiv);&lt;br /&gt;
		}&lt;br /&gt;
		return navlinkStringToHTML(s.join(&#039;&#039;), x.article, x.params);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function menuTitle(dropclass, s) {&lt;br /&gt;
		const text = popupString(s); // i18n&lt;br /&gt;
		const len = text.length;&lt;br /&gt;
		return &#039;&amp;lt;div class=&amp;quot;&#039; + dropclass + &#039;&amp;quot; style=&amp;quot;--navpop-m-len:&#039; + len + &#039;ch&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;#&amp;quot; noPopup=1&amp;gt;&#039; + text + &#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	pg.structures.menus.popupRedirTitle = pg.structures.menus.popupTitle;&lt;br /&gt;
	pg.structures.menus.popupRedirTopLinks = pg.structures.menus.popupTopLinks;&lt;br /&gt;
&lt;br /&gt;
	copyStructure(&#039;menus&#039;, &#039;shortmenus&#039;);&lt;br /&gt;
	pg.structures.shortmenus.popupTopLinks = function (x) {&lt;br /&gt;
		return pg.structures.menus.popupTopLinks(x, true);&lt;br /&gt;
	};&lt;br /&gt;
	pg.structures.shortmenus.popupRedirTopLinks = pg.structures.shortmenus.popupTopLinks;&lt;br /&gt;
&lt;br /&gt;
	pg.structures.lite = {};&lt;br /&gt;
	pg.structures.lite.popupLayout = function () {&lt;br /&gt;
		return [&#039;popupTitle&#039;, &#039;popupPreview&#039;];&lt;br /&gt;
	};&lt;br /&gt;
	pg.structures.lite.popupTitle = function (x) {&lt;br /&gt;
		log(x.article + &#039;: structures.lite.popupTitle&#039;);&lt;br /&gt;
		//return navlinkStringToHTML(&#039;&amp;lt;b&amp;gt;&amp;lt;&amp;lt;mainlink&amp;gt;&amp;gt;&amp;lt;/b&amp;gt;&#039;,x.article,x.params);&lt;br /&gt;
		return &#039;&amp;lt;div&amp;gt;&amp;lt;span class=&amp;quot;popup_mainlink&amp;quot;&amp;gt;&amp;lt;b&amp;gt;&#039; + x.article.toString() + &#039;&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
	};&lt;br /&gt;
	// ENDFILE: structures.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: autoedit.js&lt;br /&gt;
	function substitute(data, cmdBody) {&lt;br /&gt;
		// alert(&#039;sub\nfrom: &#039;+cmdBody.from+&#039;\nto: &#039;+cmdBody.to+&#039;\nflags: &#039;+cmdBody.flags);&lt;br /&gt;
		const fromRe = RegExp(cmdBody.from, cmdBody.flags);&lt;br /&gt;
		return data.replace(fromRe, cmdBody.to);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function execCmds(data, cmdList) {&lt;br /&gt;
		for (let i = 0; i &amp;lt; cmdList.length; ++i) {&lt;br /&gt;
			data = cmdList[i].action(data, cmdList[i]);&lt;br /&gt;
		}&lt;br /&gt;
		return data;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function parseCmd(str) {&lt;br /&gt;
		// returns a list of commands&lt;br /&gt;
		if (!str.length) {&lt;br /&gt;
			return [];&lt;br /&gt;
		}&lt;br /&gt;
		let p = false;&lt;br /&gt;
		switch (str.charAt(0)) {&lt;br /&gt;
			case &#039;s&#039;:&lt;br /&gt;
				p = parseSubstitute(str);&lt;br /&gt;
				break;&lt;br /&gt;
			default:&lt;br /&gt;
				return false;&lt;br /&gt;
		}&lt;br /&gt;
		if (p) {&lt;br /&gt;
			return [p].concat(parseCmd(p.remainder));&lt;br /&gt;
		}&lt;br /&gt;
		return false;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// FIXME: Only used once here, confusing with native (and more widely-used) unescape, should probably be replaced&lt;br /&gt;
	// Then again, unescape is semi-soft-deprecated, so we should look into replacing that too&lt;br /&gt;
	function unEscape(str, sep) {&lt;br /&gt;
		return str&lt;br /&gt;
			.split(&#039;\\\\&#039;)&lt;br /&gt;
			.join(&#039;\\&#039;)&lt;br /&gt;
			.split(&#039;\\&#039; + sep)&lt;br /&gt;
			.join(sep)&lt;br /&gt;
			.split(&#039;\\n&#039;)&lt;br /&gt;
			.join(&#039;\n&#039;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function parseSubstitute(str) {&lt;br /&gt;
		// takes a string like s/a/b/flags;othercmds and parses it&lt;br /&gt;
&lt;br /&gt;
		let from, to, flags, tmp;&lt;br /&gt;
&lt;br /&gt;
		if (str.length &amp;lt; 4) {&lt;br /&gt;
			return false;&lt;br /&gt;
		}&lt;br /&gt;
		const sep = str.charAt(1);&lt;br /&gt;
		str = str.substring(2);&lt;br /&gt;
&lt;br /&gt;
		tmp = skipOver(str, sep);&lt;br /&gt;
		if (tmp) {&lt;br /&gt;
			from = tmp.segment;&lt;br /&gt;
			str = tmp.remainder;&lt;br /&gt;
		} else {&lt;br /&gt;
			return false;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		tmp = skipOver(str, sep);&lt;br /&gt;
		if (tmp) {&lt;br /&gt;
			to = tmp.segment;&lt;br /&gt;
			str = tmp.remainder;&lt;br /&gt;
		} else {&lt;br /&gt;
			return false;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		flags = &#039;&#039;;&lt;br /&gt;
		if (str.length) {&lt;br /&gt;
			tmp = skipOver(str, &#039;;&#039;) || skipToEnd(str, &#039;;&#039;);&lt;br /&gt;
			if (tmp) {&lt;br /&gt;
				flags = tmp.segment;&lt;br /&gt;
				str = tmp.remainder;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		return {&lt;br /&gt;
			action: substitute,&lt;br /&gt;
			from: from,&lt;br /&gt;
			to: to,&lt;br /&gt;
			flags: flags,&lt;br /&gt;
			remainder: str,&lt;br /&gt;
		};&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function skipOver(str, sep) {&lt;br /&gt;
		const endSegment = findNext(str, sep);&lt;br /&gt;
		if (endSegment &amp;lt; 0) {&lt;br /&gt;
			return false;&lt;br /&gt;
		}&lt;br /&gt;
		const segment = unEscape(str.substring(0, endSegment), sep);&lt;br /&gt;
		return { segment: segment, remainder: str.substring(endSegment + 1) };&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/*eslint-disable*/&lt;br /&gt;
	function skipToEnd(str, sep) {&lt;br /&gt;
		return { segment: str, remainder: &#039;&#039; };&lt;br /&gt;
	}&lt;br /&gt;
	/*eslint-enable */&lt;br /&gt;
&lt;br /&gt;
	function findNext(str, ch) {&lt;br /&gt;
		for (let i = 0; i &amp;lt; str.length; ++i) {&lt;br /&gt;
			if (str.charAt(i) == &#039;\\&#039;) {&lt;br /&gt;
				i += 2;&lt;br /&gt;
			}&lt;br /&gt;
			if (str.charAt(i) == ch) {&lt;br /&gt;
				return i;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function setCheckbox(param, box) {&lt;br /&gt;
		const val = mw.util.getParamValue(param);&lt;br /&gt;
		if (val) {&lt;br /&gt;
			switch (val) {&lt;br /&gt;
				case &#039;1&#039;:&lt;br /&gt;
				case &#039;yes&#039;:&lt;br /&gt;
				case &#039;true&#039;:&lt;br /&gt;
					box.checked = true;&lt;br /&gt;
					break;&lt;br /&gt;
				case &#039;0&#039;:&lt;br /&gt;
				case &#039;no&#039;:&lt;br /&gt;
				case &#039;false&#039;:&lt;br /&gt;
					box.checked = false;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function autoEdit() {&lt;br /&gt;
		setupPopups(() =&amp;gt; {&lt;br /&gt;
			if (mw.util.getParamValue(&#039;autoimpl&#039;) !== popupString(&#039;autoedit_version&#039;)) {&lt;br /&gt;
				return false;&lt;br /&gt;
			}&lt;br /&gt;
			if (&lt;br /&gt;
				mw.util.getParamValue(&#039;autowatchlist&#039;) &amp;amp;&amp;amp;&lt;br /&gt;
				mw.util.getParamValue(&#039;actoken&#039;) === autoClickToken()&lt;br /&gt;
			) {&lt;br /&gt;
				pg.fn.modifyWatchlist(mw.util.getParamValue(&#039;title&#039;), mw.util.getParamValue(&#039;action&#039;));&lt;br /&gt;
			}&lt;br /&gt;
			if (!document.editform) {&lt;br /&gt;
				return false;&lt;br /&gt;
			}&lt;br /&gt;
			if (autoEdit.alreadyRan) {&lt;br /&gt;
				return false;&lt;br /&gt;
			}&lt;br /&gt;
			autoEdit.alreadyRan = true;&lt;br /&gt;
			const cmdString = mw.util.getParamValue(&#039;autoedit&#039;);&lt;br /&gt;
			if (cmdString) {&lt;br /&gt;
				try {&lt;br /&gt;
					const editbox = document.editform.wpTextbox1;&lt;br /&gt;
					const cmdList = parseCmd(cmdString);&lt;br /&gt;
					const input = editbox.value;&lt;br /&gt;
					const output = execCmds(input, cmdList);&lt;br /&gt;
					editbox.value = output;&lt;br /&gt;
				} catch (dang) {&lt;br /&gt;
					return;&lt;br /&gt;
				}&lt;br /&gt;
				// wikEd user script compatibility&lt;br /&gt;
				if (typeof wikEdUseWikEd != &#039;undefined&#039;) {&lt;br /&gt;
					if (wikEdUseWikEd === true) {&lt;br /&gt;
						WikEdUpdateFrame();&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			setCheckbox(&#039;autominor&#039;, document.editform.wpMinoredit);&lt;br /&gt;
			setCheckbox(&#039;autowatch&#039;, document.editform.wpWatchthis);&lt;br /&gt;
&lt;br /&gt;
			const rvid = mw.util.getParamValue(&#039;autorv&#039;);&lt;br /&gt;
			if (rvid) {&lt;br /&gt;
				const url =&lt;br /&gt;
					pg.wiki.apiwikibase +&lt;br /&gt;
					&#039;?action=query&amp;amp;format=json&amp;amp;formatversion=2&amp;amp;prop=revisions&amp;amp;revids=&#039; +&lt;br /&gt;
					rvid;&lt;br /&gt;
				startDownload(url, null, autoEdit2);&lt;br /&gt;
			} else {&lt;br /&gt;
				autoEdit2();&lt;br /&gt;
			}&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function autoEdit2(d) {&lt;br /&gt;
		let summary = mw.util.getParamValue(&#039;autosummary&#039;);&lt;br /&gt;
		let summaryprompt = mw.util.getParamValue(&#039;autosummaryprompt&#039;);&lt;br /&gt;
		let summarynotice = &#039;&#039;;&lt;br /&gt;
		if (d &amp;amp;&amp;amp; d.data &amp;amp;&amp;amp; mw.util.getParamValue(&#039;autorv&#039;)) {&lt;br /&gt;
			const s = getRvSummary(summary, d.data);&lt;br /&gt;
			if (s === false) {&lt;br /&gt;
				summaryprompt = true;&lt;br /&gt;
				summarynotice = popupString(&lt;br /&gt;
					&#039;Failed to get revision information, please edit manually.\n\n&#039;&lt;br /&gt;
				);&lt;br /&gt;
				summary = simplePrintf(summary, [&lt;br /&gt;
					mw.util.getParamValue(&#039;autorv&#039;),&lt;br /&gt;
					&#039;(unknown)&#039;,&lt;br /&gt;
					&#039;(unknown)&#039;,&lt;br /&gt;
				]);&lt;br /&gt;
			} else {&lt;br /&gt;
				summary = s;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		if (summaryprompt) {&lt;br /&gt;
			const txt =&lt;br /&gt;
				summarynotice + popupString(&#039;Enter a non-empty edit summary or press cancel to abort&#039;);&lt;br /&gt;
			const response = prompt(txt, summary);&lt;br /&gt;
			if (response) {&lt;br /&gt;
				summary = response;&lt;br /&gt;
			} else {&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		if (summary) {&lt;br /&gt;
			document.editform.wpSummary.value = summary;&lt;br /&gt;
		}&lt;br /&gt;
		// Attempt to avoid possible premature clicking of the save button&lt;br /&gt;
		// (maybe delays in updates to the DOM are to blame?? or a red herring)&lt;br /&gt;
		setTimeout(autoEdit3, 100);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function autoClickToken() {&lt;br /&gt;
		return mw.user.sessionId();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function autoEdit3() {&lt;br /&gt;
		if (mw.util.getParamValue(&#039;actoken&#039;) != autoClickToken()) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const btn = mw.util.getParamValue(&#039;autoclick&#039;);&lt;br /&gt;
		if (btn) {&lt;br /&gt;
			if (document.editform &amp;amp;&amp;amp; document.editform[btn]) {&lt;br /&gt;
				const button = document.editform[btn];&lt;br /&gt;
				const msg = tprintf(&lt;br /&gt;
					&#039;The %s button has been automatically clicked. Please wait for the next page to load.&#039;,&lt;br /&gt;
					[button.value]&lt;br /&gt;
				);&lt;br /&gt;
				bannerMessage(msg);&lt;br /&gt;
				document.title = &#039;(&#039; + document.title + &#039;)&#039;;&lt;br /&gt;
				button.click();&lt;br /&gt;
			} else {&lt;br /&gt;
				alert(&lt;br /&gt;
					tprintf(&#039;Could not find button %s. Please check the settings in your javascript file.&#039;, [&lt;br /&gt;
						btn,&lt;br /&gt;
					])&lt;br /&gt;
				);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function bannerMessage(s) {&lt;br /&gt;
		const headings = document.getElementsByTagName(&#039;h1&#039;);&lt;br /&gt;
		if (headings) {&lt;br /&gt;
			const div = document.createElement(&#039;div&#039;);&lt;br /&gt;
			div.innerHTML = &#039;&amp;lt;font size=+1&amp;gt;&amp;lt;b&amp;gt;&#039; + pg.escapeQuotesHTML(s) + &#039;&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&#039;;&lt;br /&gt;
			headings[0].parentNode.insertBefore(div, headings[0]);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function getRvSummary(template, json) {&lt;br /&gt;
		try {&lt;br /&gt;
			const o = getJsObj(json);&lt;br /&gt;
			const edit = anyChild(o.query.pages).revisions[0];&lt;br /&gt;
			const timestamp = edit.timestamp&lt;br /&gt;
				.split(/[A-Z]/g)&lt;br /&gt;
				.join(&#039; &#039;)&lt;br /&gt;
				.replace(/^ *| *$/g, &#039;&#039;);&lt;br /&gt;
			return simplePrintf(template, [&lt;br /&gt;
				edit.revid,&lt;br /&gt;
				timestamp,&lt;br /&gt;
				edit.userhidden ? &#039;(hidden)&#039; : edit.user,&lt;br /&gt;
			]);&lt;br /&gt;
		} catch (badness) {&lt;br /&gt;
			return false;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ENDFILE: autoedit.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: downloader.js&lt;br /&gt;
	/**&lt;br /&gt;
	 * @file&lt;br /&gt;
	 * {@link Downloader}, a xmlhttprequest wrapper, and helper functions.&lt;br /&gt;
	 */&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Creates a new Downloader&lt;br /&gt;
	 *&lt;br /&gt;
	 * @constructor&lt;br /&gt;
	 * @class The Downloader class. Create a new instance of this class to download stuff.&lt;br /&gt;
	 * @param {string} url The url to download. This can be omitted and supplied later.&lt;br /&gt;
	 */&lt;br /&gt;
	function Downloader(url) {&lt;br /&gt;
		if (typeof XMLHttpRequest != &#039;undefined&#039;) {&lt;br /&gt;
			this.http = new XMLHttpRequest();&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
		 * The url to download&lt;br /&gt;
		 *&lt;br /&gt;
		 * @type {string}&lt;br /&gt;
		 */&lt;br /&gt;
		this.url = url;&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
		 * A universally unique ID number&lt;br /&gt;
		 *&lt;br /&gt;
		 * @type {number}&lt;br /&gt;
		 */&lt;br /&gt;
		this.id = null;&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
		 * Modification date, to be culled from the incoming headers&lt;br /&gt;
		 *&lt;br /&gt;
		 * @type {Date}&lt;br /&gt;
		 * @private&lt;br /&gt;
		 */&lt;br /&gt;
		this.lastModified = null;&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
		 * What to do when the download completes successfully&lt;br /&gt;
		 *&lt;br /&gt;
		 * @type {Function}&lt;br /&gt;
		 * @private&lt;br /&gt;
		 */&lt;br /&gt;
		this.callbackFunction = null;&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
		 * What to do on failure&lt;br /&gt;
		 *&lt;br /&gt;
		 * @type {Function}&lt;br /&gt;
		 * @private&lt;br /&gt;
		 */&lt;br /&gt;
		this.onFailure = null;&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
		 * Flag set on &amp;lt;code&amp;gt;abort&amp;lt;/code&amp;gt;&lt;br /&gt;
		 *&lt;br /&gt;
		 * @type {boolean}&lt;br /&gt;
		 */&lt;br /&gt;
		this.aborted = false;&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
		 * HTTP method. See https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html for&lt;br /&gt;
		 * possibilities.&lt;br /&gt;
		 *&lt;br /&gt;
		 * @type {string}&lt;br /&gt;
		 */&lt;br /&gt;
		this.method = &#039;GET&#039;;&lt;br /&gt;
		/**&lt;br /&gt;
		 * Async flag.&lt;br /&gt;
		 *&lt;br /&gt;
		 * @type {boolean}&lt;br /&gt;
		 */&lt;br /&gt;
		this.async = true;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	new Downloader();&lt;br /&gt;
&lt;br /&gt;
	/** Submits the http request. */&lt;br /&gt;
	Downloader.prototype.send = function (x) {&lt;br /&gt;
		if (!this.http) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
		return this.http.send(x);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/** Aborts the download, setting the &amp;lt;code&amp;gt;aborted&amp;lt;/code&amp;gt; field to true.  */&lt;br /&gt;
	Downloader.prototype.abort = function () {&lt;br /&gt;
		if (!this.http) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
		this.aborted = true;&lt;br /&gt;
		return this.http.abort();&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/** Returns the downloaded data. */&lt;br /&gt;
	Downloader.prototype.getData = function () {&lt;br /&gt;
		if (!this.http) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
		return this.http.responseText;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/** Prepares the download. */&lt;br /&gt;
	Downloader.prototype.setTarget = function () {&lt;br /&gt;
		if (!this.http) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
		this.http.open(this.method, this.url, this.async);&lt;br /&gt;
		this.http.setRequestHeader(&#039;Api-User-Agent&#039;, pg.api.userAgent);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/** Gets the state of the download. */&lt;br /&gt;
	Downloader.prototype.getReadyState = function () {&lt;br /&gt;
		if (!this.http) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
		return this.http.readyState;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	pg.misc.downloadsInProgress = {};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Starts the download.&lt;br /&gt;
	 * Note that setTarget {@link Downloader#setTarget} must be run first&lt;br /&gt;
	 */&lt;br /&gt;
	Downloader.prototype.start = function () {&lt;br /&gt;
		if (!this.http) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		pg.misc.downloadsInProgress[this.id] = this;&lt;br /&gt;
		this.http.send(null);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Gets the &#039;Last-Modified&#039; date from the download headers.&lt;br /&gt;
	 * Should be run after the download completes.&lt;br /&gt;
	 * Returns &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; on failure.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return {Date}&lt;br /&gt;
	 */&lt;br /&gt;
	Downloader.prototype.getLastModifiedDate = function () {&lt;br /&gt;
		if (!this.http) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
		let lastmod = null;&lt;br /&gt;
		try {&lt;br /&gt;
			lastmod = this.http.getResponseHeader(&#039;Last-Modified&#039;);&lt;br /&gt;
		} catch (err) {}&lt;br /&gt;
		if (lastmod) {&lt;br /&gt;
			return new Date(lastmod);&lt;br /&gt;
		}&lt;br /&gt;
		return null;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Sets the callback function.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param {Function} f callback function, called as &amp;lt;code&amp;gt;f(this)&amp;lt;/code&amp;gt; on success&lt;br /&gt;
	 */&lt;br /&gt;
	Downloader.prototype.setCallback = function (f) {&lt;br /&gt;
		if (!this.http) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		this.http.onreadystatechange = f;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	Downloader.prototype.getStatus = function () {&lt;br /&gt;
		if (!this.http) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
		return this.http.status;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	//////////////////////////////////////////////////&lt;br /&gt;
	// helper functions&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Creates a new {@link Downloader} and prepares it for action.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param {string} url The url to download&lt;br /&gt;
	 * @param {number} id The ID of the {@link Downloader} object&lt;br /&gt;
	 * @param {Function} callback The callback function invoked on success&lt;br /&gt;
	 * @return {string|Downloader} the {@link Downloader} object created, or &#039;ohdear&#039; if an unsupported browser&lt;br /&gt;
	 */&lt;br /&gt;
	function newDownload(url, id, callback, onfailure) {&lt;br /&gt;
		const d = new Downloader(url);&lt;br /&gt;
		if (!d.http) {&lt;br /&gt;
			return &#039;ohdear&#039;;&lt;br /&gt;
		}&lt;br /&gt;
		d.id = id;&lt;br /&gt;
		d.setTarget();&lt;br /&gt;
		if (!onfailure) {&lt;br /&gt;
			onfailure = 2;&lt;br /&gt;
		}&lt;br /&gt;
		const f = function () {&lt;br /&gt;
			if (d.getReadyState() == 4) {&lt;br /&gt;
				delete pg.misc.downloadsInProgress[this.id];&lt;br /&gt;
				try {&lt;br /&gt;
					if (d.getStatus() == 200) {&lt;br /&gt;
						d.data = d.getData();&lt;br /&gt;
						d.lastModified = d.getLastModifiedDate();&lt;br /&gt;
						callback(d);&lt;br /&gt;
					} else if (typeof onfailure == typeof 1) {&lt;br /&gt;
						if (onfailure &amp;gt; 0) {&lt;br /&gt;
							// retry&lt;br /&gt;
							newDownload(url, id, callback, onfailure - 1);&lt;br /&gt;
						}&lt;br /&gt;
					} else if (typeof onfailure === &#039;function&#039;) {&lt;br /&gt;
						onfailure(d, url, id, callback);&lt;br /&gt;
					}&lt;br /&gt;
				} catch (somerr) {&lt;br /&gt;
					/* ignore it */&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		};&lt;br /&gt;
		d.setCallback(f);&lt;br /&gt;
		return d;&lt;br /&gt;
	}&lt;br /&gt;
	/**&lt;br /&gt;
	 * Simulates a download from cached data.&lt;br /&gt;
	 * The supplied data is put into a {@link Downloader} as if it had downloaded it.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param {string} url The url.&lt;br /&gt;
	 * @param {number} id The ID.&lt;br /&gt;
	 * @param {Function} callback The callback, which is invoked immediately as &amp;lt;code&amp;gt;callback(d)&amp;lt;/code&amp;gt;,&lt;br /&gt;
	 * where &amp;lt;code&amp;gt;d&amp;lt;/code&amp;gt; is the new {@link Downloader}.&lt;br /&gt;
	 * @param {string} data The (cached) data.&lt;br /&gt;
	 * @param {Date} lastModified The (cached) last modified date.&lt;br /&gt;
	 */&lt;br /&gt;
	function fakeDownload(url, id, callback, data, lastModified, owner) {&lt;br /&gt;
		const d = newDownload(url, callback);&lt;br /&gt;
		d.owner = owner;&lt;br /&gt;
		d.id = id;&lt;br /&gt;
		d.data = data;&lt;br /&gt;
		d.lastModified = lastModified;&lt;br /&gt;
		return callback(d);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Starts a download.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param {string} url The url to download&lt;br /&gt;
	 * @param {number} id The ID of the {@link Downloader} object&lt;br /&gt;
	 * @param {Function} callback The callback function invoked on success&lt;br /&gt;
	 * @return {string|Downloader} the {@link Downloader} object created, or &#039;ohdear&#039; if an unsupported browser&lt;br /&gt;
	 */&lt;br /&gt;
	function startDownload(url, id, callback) {&lt;br /&gt;
		const d = newDownload(url, id, callback);&lt;br /&gt;
		if (typeof d == typeof &#039;&#039;) {&lt;br /&gt;
			return d;&lt;br /&gt;
		}&lt;br /&gt;
		d.start();&lt;br /&gt;
		return d;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Aborts all downloads which have been started.&lt;br /&gt;
	 */&lt;br /&gt;
	function abortAllDownloads() {&lt;br /&gt;
		for (const x in pg.misc.downloadsInProgress) {&lt;br /&gt;
			try {&lt;br /&gt;
				pg.misc.downloadsInProgress[x].aborted = true;&lt;br /&gt;
				pg.misc.downloadsInProgress[x].abort();&lt;br /&gt;
				delete pg.misc.downloadsInProgress[x];&lt;br /&gt;
			} catch (e) {}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	// ENDFILE: downloader.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: livepreview.js&lt;br /&gt;
	// TODO: location is often not correct (eg relative links in previews)&lt;br /&gt;
	// NOTE: removed md5 and image and math parsing. was broken, lots of bytes.&lt;br /&gt;
	/**&lt;br /&gt;
	 * InstaView - a Mediawiki to HTML converter in JavaScript&lt;br /&gt;
	 * Version 0.6.1&lt;br /&gt;
	 * Copyright (C) Pedro Fayolle 2005-2006&lt;br /&gt;
	 * https://en.wikipedia.org/wiki/User:Pilaf&lt;br /&gt;
	 * Distributed under the BSD license&lt;br /&gt;
	 *&lt;br /&gt;
	 * Changelog:&lt;br /&gt;
	 *&lt;br /&gt;
	 * 0.6.1&lt;br /&gt;
	 * - Fixed problem caused by \r characters&lt;br /&gt;
	 * - Improved inline formatting parser&lt;br /&gt;
	 *&lt;br /&gt;
	 * 0.6&lt;br /&gt;
	 * - Changed name to InstaView&lt;br /&gt;
	 * - Some major code reorganizations and factored out some common functions&lt;br /&gt;
	 * - Handled conversion of relative links (i.e. [[/foo]])&lt;br /&gt;
	 * - Fixed misrendering of adjacent definition list items&lt;br /&gt;
	 * - Fixed bug in table headings handling&lt;br /&gt;
	 * - Changed date format in signatures to reflect Mediawiki&#039;s&lt;br /&gt;
	 * - Fixed handling of [[:Image:...]]&lt;br /&gt;
	 * - Updated MD5 function (hopefully it will work with UTF-8)&lt;br /&gt;
	 * - Fixed bug in handling of links inside images&lt;br /&gt;
	 *&lt;br /&gt;
	 * To do:&lt;br /&gt;
	 * - Better support for math tags&lt;br /&gt;
	 * - Full support for &amp;lt;nowiki&amp;gt;&lt;br /&gt;
	 * - Parser-based (as opposed to RegExp-based) inline wikicode handling (make it one-pass and&lt;br /&gt;
	 *   bullet-proof)&lt;br /&gt;
	 * - Support for templates (through AJAX)&lt;br /&gt;
	 * - Support for coloured links (AJAX)&lt;br /&gt;
	 */&lt;br /&gt;
&lt;br /&gt;
	const Insta = {};&lt;br /&gt;
&lt;br /&gt;
	function setupLivePreview() {&lt;br /&gt;
		// options&lt;br /&gt;
		Insta.conf = {&lt;br /&gt;
			baseUrl: &#039;&#039;,&lt;br /&gt;
&lt;br /&gt;
			user: {},&lt;br /&gt;
&lt;br /&gt;
			wiki: {&lt;br /&gt;
				lang: pg.wiki.lang,&lt;br /&gt;
				interwiki: pg.wiki.interwiki,&lt;br /&gt;
				default_thumb_width: 180,&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			paths: {&lt;br /&gt;
				articles: pg.wiki.articlePath + &#039;/&#039;,&lt;br /&gt;
				// Only used for Insta previews with images. (not in popups)&lt;br /&gt;
				math: &#039;/math/&#039;,&lt;br /&gt;
				images: &#039;//upload.wikimedia.org/wikipedia/en/&#039;, // FIXME getImageUrlStart(pg.wiki.hostname),&lt;br /&gt;
				images_fallback: &#039;//upload.wikimedia.org/wikipedia/commons/&#039;,&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			locale: {&lt;br /&gt;
				user: mw.config.get(&#039;wgFormattedNamespaces&#039;)[pg.nsUserId],&lt;br /&gt;
				image: mw.config.get(&#039;wgFormattedNamespaces&#039;)[pg.nsImageId],&lt;br /&gt;
				category: mw.config.get(&#039;wgFormattedNamespaces&#039;)[pg.nsCategoryId],&lt;br /&gt;
				// shouldn&#039;t be used in popup previews, i think&lt;br /&gt;
				months: [&lt;br /&gt;
					&#039;Jan&#039;,&lt;br /&gt;
					&#039;Feb&#039;,&lt;br /&gt;
					&#039;Mar&#039;,&lt;br /&gt;
					&#039;Apr&#039;,&lt;br /&gt;
					&#039;May&#039;,&lt;br /&gt;
					&#039;Jun&#039;,&lt;br /&gt;
					&#039;Jul&#039;,&lt;br /&gt;
					&#039;Aug&#039;,&lt;br /&gt;
					&#039;Sep&#039;,&lt;br /&gt;
					&#039;Oct&#039;,&lt;br /&gt;
					&#039;Nov&#039;,&lt;br /&gt;
					&#039;Dec&#039;,&lt;br /&gt;
				],&lt;br /&gt;
			},&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		// options with default values or backreferences&lt;br /&gt;
		Insta.conf.user.name = Insta.conf.user.name || &#039;Wikipedian&#039;;&lt;br /&gt;
		Insta.conf.user.signature =&lt;br /&gt;
			&#039;[[&#039; +&lt;br /&gt;
			Insta.conf.locale.user +&lt;br /&gt;
			&#039;:&#039; +&lt;br /&gt;
			Insta.conf.user.name +&lt;br /&gt;
			&#039;|&#039; +&lt;br /&gt;
			Insta.conf.user.name +&lt;br /&gt;
			&#039;]]&#039;;&lt;br /&gt;
		//Insta.conf.paths.images = &#039;//upload.wikimedia.org/wikipedia/&#039; + Insta.conf.wiki.lang + &#039;/&#039;;&lt;br /&gt;
&lt;br /&gt;
		// define constants&lt;br /&gt;
		Insta.BLOCK_IMAGE = new RegExp(&lt;br /&gt;
			&#039;^\\[\\[(?:File|Image|&#039; +&lt;br /&gt;
				Insta.conf.locale.image +&lt;br /&gt;
				&#039;):.*?\\|.*?(?:frame|thumbnail|thumb|none|right|left|center)&#039;,&lt;br /&gt;
			&#039;i&#039;&lt;br /&gt;
		);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	Insta.dump = function (from, to) {&lt;br /&gt;
		if (typeof from == &#039;string&#039;) {&lt;br /&gt;
			from = document.getElementById(from);&lt;br /&gt;
		}&lt;br /&gt;
		if (typeof to == &#039;string&#039;) {&lt;br /&gt;
			to = document.getElementById(to);&lt;br /&gt;
		}&lt;br /&gt;
		to.innerHTML = this.convert(from.value);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	Insta.convert = function (wiki) {&lt;br /&gt;
		let ll = typeof wiki == &#039;string&#039; ? wiki.replace(/\r/g, &#039;&#039;).split(/\n/) : wiki, // lines of wikicode&lt;br /&gt;
			o = &#039;&#039;, // output&lt;br /&gt;
			p = 0, // para flag&lt;br /&gt;
			r; // result of passing a regexp to compareLineStringOrReg()&lt;br /&gt;
&lt;br /&gt;
		// some shorthands&lt;br /&gt;
		function remain() {&lt;br /&gt;
			return ll.length;&lt;br /&gt;
		}&lt;br /&gt;
		function sh() {&lt;br /&gt;
			return ll.shift();&lt;br /&gt;
		} // shift&lt;br /&gt;
		function ps(s) {&lt;br /&gt;
			o += s;&lt;br /&gt;
		} // push&lt;br /&gt;
&lt;br /&gt;
		// similar to C&#039;s printf, uses ? as placeholders, ?? to escape question marks&lt;br /&gt;
		function f() {&lt;br /&gt;
			let i = 1,&lt;br /&gt;
				a = arguments,&lt;br /&gt;
				f = a[0],&lt;br /&gt;
				o = &#039;&#039;,&lt;br /&gt;
				c,&lt;br /&gt;
				p;&lt;br /&gt;
			for (; i &amp;lt; a.length; i++) {&lt;br /&gt;
				if ((p = f.indexOf(&#039;?&#039;)) + 1) {&lt;br /&gt;
					// allow character escaping&lt;br /&gt;
					i -= c = f.charAt(p + 1) == &#039;?&#039; ? 1 : 0;&lt;br /&gt;
					o += f.substring(0, p) + (c ? &#039;?&#039; : a[i]);&lt;br /&gt;
					f = f.substr(p + 1 + c);&lt;br /&gt;
				} else {&lt;br /&gt;
					break;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return o + f;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		function html_entities(s) {&lt;br /&gt;
			return s.replace(/&amp;amp;/g, &#039;&amp;amp;amp;&#039;).replace(/&amp;lt;/g, &#039;&amp;amp;lt;&#039;).replace(/&amp;gt;/g, &#039;&amp;amp;gt;&#039;);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Wiki text parsing to html is a nightmare.&lt;br /&gt;
		// The below functions deliberately don&#039;t escape the ampersand since this would make it more&lt;br /&gt;
		// difficult, and we don&#039;t absolutely need to for how we need it. This means that any&lt;br /&gt;
		// unescaped ampersands in wikitext will remain unescaped and can cause invalid HTML.&lt;br /&gt;
		// Browsers should all be able to handle it though. We also escape significant wikimarkup&lt;br /&gt;
		// characters to prevent further matching on the processed text.&lt;br /&gt;
		function htmlescape_text(s) {&lt;br /&gt;
			return s&lt;br /&gt;
				.replace(/&amp;lt;/g, &#039;&amp;amp;lt;&#039;)&lt;br /&gt;
				.replace(/&amp;gt;/g, &#039;&amp;amp;gt;&#039;)&lt;br /&gt;
				.replace(/:/g, &#039;&amp;amp;#58;&#039;)&lt;br /&gt;
				.replace(/\[/g, &#039;&amp;amp;#91;&#039;)&lt;br /&gt;
				.replace(/]/g, &#039;&amp;amp;#93;&#039;);&lt;br /&gt;
		}&lt;br /&gt;
		function htmlescape_attr(s) {&lt;br /&gt;
			return htmlescape_text(s).replace(/&#039;/g, &#039;&amp;amp;#39;&#039;).replace(/&amp;quot;/g, &#039;&amp;amp;quot;&#039;);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// return the first non matching character position between two strings&lt;br /&gt;
		function str_imatch(a, b) {&lt;br /&gt;
			for (var i = 0, l = Math.min(a.length, b.length); i &amp;lt; l; i++) {&lt;br /&gt;
				if (a.charAt(i) != b.charAt(i)) {&lt;br /&gt;
					break;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return i;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// compare current line against a string or regexp&lt;br /&gt;
		// if passed a string it will compare only the first string.length characters&lt;br /&gt;
		// if passed a regexp the result is stored in r&lt;br /&gt;
		function compareLineStringOrReg(c) {&lt;br /&gt;
			return typeof c == &#039;string&#039; ?&lt;br /&gt;
				ll[0] &amp;amp;&amp;amp; ll[0].substr(0, c.length) == c :&lt;br /&gt;
				(r = ll[0] &amp;amp;&amp;amp; ll[0].match(c));&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		function compareLineString(c) {&lt;br /&gt;
			return ll[0] == c;&lt;br /&gt;
		} // compare current line against a string&lt;br /&gt;
		function charAtPoint(p) {&lt;br /&gt;
			return ll[0].charAt(p);&lt;br /&gt;
		} // return char at pos p&lt;br /&gt;
&lt;br /&gt;
		function endl(s) {&lt;br /&gt;
			ps(s);&lt;br /&gt;
			sh();&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		function parse_list() {&lt;br /&gt;
			let prev = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
			while (remain() &amp;amp;&amp;amp; compareLineStringOrReg(/^([*#:;]+)(.*)$/)) {&lt;br /&gt;
				const l_match = r;&lt;br /&gt;
&lt;br /&gt;
				sh();&lt;br /&gt;
&lt;br /&gt;
				const ipos = str_imatch(prev, l_match[1]);&lt;br /&gt;
&lt;br /&gt;
				// close uncontinued lists&lt;br /&gt;
				for (let prevPos = prev.length - 1; prevPos &amp;gt;= ipos; prevPos--) {&lt;br /&gt;
					const pi = prev.charAt(prevPos);&lt;br /&gt;
&lt;br /&gt;
					if (pi == &#039;*&#039;) {&lt;br /&gt;
						ps(&#039;&amp;lt;/ul&amp;gt;&#039;);&lt;br /&gt;
					} else if (pi == &#039;#&#039;) {&lt;br /&gt;
						ps(&#039;&amp;lt;/ol&amp;gt;&#039;);&lt;br /&gt;
					}&lt;br /&gt;
					// close a dl only if the new item is not a dl item (:, ; or empty)&lt;br /&gt;
					else if ($.inArray(l_match[1].charAt(prevPos), [&#039;&#039;, &#039;*&#039;, &#039;#&#039;])) {&lt;br /&gt;
						ps(&#039;&amp;lt;/dl&amp;gt;&#039;);&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				// open new lists&lt;br /&gt;
				for (let matchPos = ipos; matchPos &amp;lt; l_match[1].length; matchPos++) {&lt;br /&gt;
					const li = l_match[1].charAt(matchPos);&lt;br /&gt;
&lt;br /&gt;
					if (li == &#039;*&#039;) {&lt;br /&gt;
						ps(&#039;&amp;lt;ul&amp;gt;&#039;);&lt;br /&gt;
					} else if (li == &#039;#&#039;) {&lt;br /&gt;
						ps(&#039;&amp;lt;ol&amp;gt;&#039;);&lt;br /&gt;
					}&lt;br /&gt;
					// open a new dl only if the prev item is not a dl item (:, ; or empty)&lt;br /&gt;
					else if ($.inArray(prev.charAt(matchPos), [&#039;&#039;, &#039;*&#039;, &#039;#&#039;])) {&lt;br /&gt;
						ps(&#039;&amp;lt;dl&amp;gt;&#039;);&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				switch (l_match[1].charAt(l_match[1].length - 1)) {&lt;br /&gt;
					case &#039;*&#039;:&lt;br /&gt;
					case &#039;#&#039;:&lt;br /&gt;
						ps(&#039;&amp;lt;li&amp;gt;&#039; + parse_inline_nowiki(l_match[2]));&lt;br /&gt;
						break;&lt;br /&gt;
&lt;br /&gt;
					case &#039;;&#039;:&lt;br /&gt;
						ps(&#039;&amp;lt;dt&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
						var dt_match = l_match[2].match(/(.*?)(:.*?)$/);&lt;br /&gt;
&lt;br /&gt;
						// handle ;dt :dd format&lt;br /&gt;
						if (dt_match) {&lt;br /&gt;
							ps(parse_inline_nowiki(dt_match[1]));&lt;br /&gt;
							ll.unshift(dt_match[2]);&lt;br /&gt;
						} else {&lt;br /&gt;
							ps(parse_inline_nowiki(l_match[2]));&lt;br /&gt;
						}&lt;br /&gt;
						break;&lt;br /&gt;
&lt;br /&gt;
					case &#039;:&#039;:&lt;br /&gt;
						ps(&#039;&amp;lt;dd&amp;gt;&#039; + parse_inline_nowiki(l_match[2]));&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				prev = l_match[1];&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			// close remaining lists&lt;br /&gt;
			for (let i = prev.length - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
				ps(f(&#039;&amp;lt;/?&amp;gt;&#039;, prev.charAt(i) == &#039;*&#039; ? &#039;ul&#039; : prev.charAt(i) == &#039;#&#039; ? &#039;ol&#039; : &#039;dl&#039;));&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		function parse_table() {&lt;br /&gt;
			endl(f(&#039;&amp;lt;table&amp;gt;&#039;, compareLineStringOrReg(/^\{\|( .*)$/) ? r[1] : &#039;&#039;));&lt;br /&gt;
&lt;br /&gt;
			for (; remain(); ) {&lt;br /&gt;
				if (compareLineStringOrReg(&#039;|&#039;)) {&lt;br /&gt;
					switch (charAtPoint(1)) {&lt;br /&gt;
						case &#039;}&#039;:&lt;br /&gt;
							endl(&#039;&amp;lt;/table&amp;gt;&#039;);&lt;br /&gt;
							return;&lt;br /&gt;
						case &#039;-&#039;:&lt;br /&gt;
							endl(f(&#039;&amp;lt;tr&amp;gt;&#039;, compareLineStringOrReg(/\|-*(.*)/)[1]));&lt;br /&gt;
							break;&lt;br /&gt;
						default:&lt;br /&gt;
							parse_table_data();&lt;br /&gt;
					}&lt;br /&gt;
				} else if (compareLineStringOrReg(&#039;!&#039;)) {&lt;br /&gt;
					parse_table_data();&lt;br /&gt;
				} else {&lt;br /&gt;
					sh();&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		function parse_table_data() {&lt;br /&gt;
			let td_line, match_i;&lt;br /&gt;
&lt;br /&gt;
			// 1: &amp;quot;|+&amp;quot;, &#039;|&#039; or &#039;+&#039;&lt;br /&gt;
			// 2: ??&lt;br /&gt;
			// 3: attributes ??&lt;br /&gt;
			// TODO: finish commenting this regexp&lt;br /&gt;
			const td_match = sh().match(/^(\|\+|\||!)((?:([^[|]*?)\|(?!\|))?(.*))$/);&lt;br /&gt;
&lt;br /&gt;
			if (td_match[1] == &#039;|+&#039;) {&lt;br /&gt;
				ps(&#039;&amp;lt;caption&#039;);&lt;br /&gt;
			} else {&lt;br /&gt;
				ps(&#039;&amp;lt;t&#039; + (td_match[1] == &#039;|&#039; ? &#039;d&#039; : &#039;h&#039;));&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			if (typeof td_match[3] != &#039;undefined&#039;) {&lt;br /&gt;
				//ps(&#039; &#039; + td_match[3])&lt;br /&gt;
				match_i = 4;&lt;br /&gt;
			} else {&lt;br /&gt;
				match_i = 2;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			ps(&#039;&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
			if (td_match[1] != &#039;|+&#039;) {&lt;br /&gt;
				// use || or !! as a cell separator depending on context&lt;br /&gt;
				// NOTE: when split() is passed a regexp make sure to use non-capturing brackets&lt;br /&gt;
				td_line = td_match[match_i].split(td_match[1] == &#039;|&#039; ? &#039;||&#039; : /(?:\|\||!!)/);&lt;br /&gt;
&lt;br /&gt;
				ps(parse_inline_nowiki(td_line.shift()));&lt;br /&gt;
&lt;br /&gt;
				while (td_line.length) {&lt;br /&gt;
					ll.unshift(td_match[1] + td_line.pop());&lt;br /&gt;
				}&lt;br /&gt;
			} else {&lt;br /&gt;
				ps(parse_inline_nowiki(td_match[match_i]));&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			let tc = 0,&lt;br /&gt;
				td = [];&lt;br /&gt;
&lt;br /&gt;
			while (remain()) {&lt;br /&gt;
				td.push(sh());&lt;br /&gt;
				if (compareLineStringOrReg(&#039;|&#039;)) {&lt;br /&gt;
					if (!tc) {&lt;br /&gt;
						break;&lt;br /&gt;
					}&lt;br /&gt;
					// we&#039;re at the outer-most level (no nested tables), skip to td parse&lt;br /&gt;
					else if (charAtPoint(1) == &#039;}&#039;) {&lt;br /&gt;
						tc--;&lt;br /&gt;
					}&lt;br /&gt;
				} else if (!tc &amp;amp;&amp;amp; compareLineStringOrReg(&#039;!&#039;)) {&lt;br /&gt;
					break;&lt;br /&gt;
				} else if (compareLineStringOrReg(&#039;{|&#039;)) {&lt;br /&gt;
					tc++;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			if (td.length) {&lt;br /&gt;
				ps(Insta.convert(td));&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		function parse_pre() {&lt;br /&gt;
			ps(&#039;&amp;lt;pre&amp;gt;&#039;);&lt;br /&gt;
			do {&lt;br /&gt;
				endl(parse_inline_nowiki(ll[0].substring(1)) + &#039;\n&#039;);&lt;br /&gt;
			} while (remain() &amp;amp;&amp;amp; compareLineStringOrReg(&#039; &#039;));&lt;br /&gt;
			ps(&#039;&amp;lt;/pre&amp;gt;&#039;);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		function parse_block_image() {&lt;br /&gt;
			ps(parse_image(sh()));&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		function parse_image(str) {&lt;br /&gt;
			// get what&#039;s in between &amp;quot;[[Image:&amp;quot; and &amp;quot;]]&amp;quot;&lt;br /&gt;
			let tag = str.substring(str.indexOf(&#039;:&#039;) + 1, str.length - 2);&lt;br /&gt;
			let width;&lt;br /&gt;
			let attr = [],&lt;br /&gt;
				filename,&lt;br /&gt;
				caption = &#039;&#039;;&lt;br /&gt;
			let thumb = 0,&lt;br /&gt;
				frame = 0,&lt;br /&gt;
				center = 0;&lt;br /&gt;
			let align = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
			if (tag.match(/\|/)) {&lt;br /&gt;
				// manage nested links&lt;br /&gt;
				let nesting = 0;&lt;br /&gt;
				let last_attr;&lt;br /&gt;
				for (let i = tag.length - 1; i &amp;gt; 0; i--) {&lt;br /&gt;
					if (tag.charAt(i) == &#039;|&#039; &amp;amp;&amp;amp; !nesting) {&lt;br /&gt;
						last_attr = tag.substr(i + 1);&lt;br /&gt;
						tag = tag.substring(0, i);&lt;br /&gt;
						break;&lt;br /&gt;
					} else {&lt;br /&gt;
						switch (tag.substr(i - 1, 2)) {&lt;br /&gt;
							case &#039;]]&#039;:&lt;br /&gt;
								nesting++;&lt;br /&gt;
								i--;&lt;br /&gt;
								break;&lt;br /&gt;
							case &#039;[[&#039;:&lt;br /&gt;
								nesting--;&lt;br /&gt;
								i--;&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				attr = tag.split(/\s*\|\s*/);&lt;br /&gt;
				attr.push(last_attr);&lt;br /&gt;
				filename = attr.shift();&lt;br /&gt;
&lt;br /&gt;
				let w_match;&lt;br /&gt;
&lt;br /&gt;
				for (; attr.length; attr.shift()) {&lt;br /&gt;
					w_match = attr[0].match(/^(\d*)(?:[px]*\d*)?px$/);&lt;br /&gt;
					if (w_match) {&lt;br /&gt;
						width = w_match[1];&lt;br /&gt;
					} else {&lt;br /&gt;
						switch (attr[0]) {&lt;br /&gt;
							case &#039;thumb&#039;:&lt;br /&gt;
							case &#039;thumbnail&#039;:&lt;br /&gt;
								thumb = true;&lt;br /&gt;
								frame = true;&lt;br /&gt;
								break;&lt;br /&gt;
							case &#039;frame&#039;:&lt;br /&gt;
								frame = true;&lt;br /&gt;
								break;&lt;br /&gt;
							case &#039;none&#039;:&lt;br /&gt;
							case &#039;right&#039;:&lt;br /&gt;
							case &#039;left&#039;:&lt;br /&gt;
								center = false;&lt;br /&gt;
								align = attr[0];&lt;br /&gt;
								break;&lt;br /&gt;
							case &#039;center&#039;:&lt;br /&gt;
								center = true;&lt;br /&gt;
								align = &#039;none&#039;;&lt;br /&gt;
								break;&lt;br /&gt;
							default:&lt;br /&gt;
								if (attr.length == 1) {&lt;br /&gt;
									caption = attr[0];&lt;br /&gt;
								}&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			} else {&lt;br /&gt;
				filename = tag;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			return &#039;&#039;;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		function parse_inline_nowiki(str) {&lt;br /&gt;
			let start,&lt;br /&gt;
				lastend = 0;&lt;br /&gt;
			let substart = 0,&lt;br /&gt;
				nestlev = 0,&lt;br /&gt;
				open,&lt;br /&gt;
				close,&lt;br /&gt;
				subloop;&lt;br /&gt;
			let html = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
			while ((start = str.indexOf(&#039;&amp;lt;nowiki&amp;gt;&#039;, substart)) != -1) {&lt;br /&gt;
				html += parse_inline_wiki(str.substring(lastend, start));&lt;br /&gt;
				start += 8;&lt;br /&gt;
				substart = start;&lt;br /&gt;
				subloop = true;&lt;br /&gt;
				do {&lt;br /&gt;
					open = str.indexOf(&#039;&amp;lt;nowiki&amp;gt;&#039;, substart);&lt;br /&gt;
					close = str.indexOf(&#039;&amp;lt;/nowiki&amp;gt;&#039;, substart);&lt;br /&gt;
					if (close &amp;lt;= open || open == -1) {&lt;br /&gt;
						if (close == -1) {&lt;br /&gt;
							return html + html_entities(str.substr(start));&lt;br /&gt;
						}&lt;br /&gt;
						substart = close + 9;&lt;br /&gt;
						if (nestlev) {&lt;br /&gt;
							nestlev--;&lt;br /&gt;
						} else {&lt;br /&gt;
							lastend = substart;&lt;br /&gt;
							html += html_entities(str.substring(start, lastend - 9));&lt;br /&gt;
							subloop = false;&lt;br /&gt;
						}&lt;br /&gt;
					} else {&lt;br /&gt;
						substart = open + 8;&lt;br /&gt;
						nestlev++;&lt;br /&gt;
					}&lt;br /&gt;
				} while (subloop);&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			return html + parse_inline_wiki(str.substr(lastend));&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		function parse_inline_images(str) {&lt;br /&gt;
			let start,&lt;br /&gt;
				substart = 0,&lt;br /&gt;
				nestlev = 0;&lt;br /&gt;
			let loop, close, open, wiki, html;&lt;br /&gt;
&lt;br /&gt;
			while ((start = str.indexOf(&#039;[[&#039;, substart)) != -1) {&lt;br /&gt;
				if (&lt;br /&gt;
					str.substr(start + 2).match(RegExp(&#039;^(Image|File|&#039; + Insta.conf.locale.image + &#039;):&#039;, &#039;i&#039;))&lt;br /&gt;
				) {&lt;br /&gt;
					loop = true;&lt;br /&gt;
					substart = start;&lt;br /&gt;
					do {&lt;br /&gt;
						substart += 2;&lt;br /&gt;
						close = str.indexOf(&#039;]]&#039;, substart);&lt;br /&gt;
						open = str.indexOf(&#039;[[&#039;, substart);&lt;br /&gt;
						if (close &amp;lt;= open || open == -1) {&lt;br /&gt;
							if (close == -1) {&lt;br /&gt;
								return str;&lt;br /&gt;
							}&lt;br /&gt;
							substart = close;&lt;br /&gt;
							if (nestlev) {&lt;br /&gt;
								nestlev--;&lt;br /&gt;
							} else {&lt;br /&gt;
								wiki = str.substring(start, close + 2);&lt;br /&gt;
								html = parse_image(wiki);&lt;br /&gt;
								str = str.replace(wiki, html);&lt;br /&gt;
								substart = start + html.length;&lt;br /&gt;
								loop = false;&lt;br /&gt;
							}&lt;br /&gt;
						} else {&lt;br /&gt;
							substart = open;&lt;br /&gt;
							nestlev++;&lt;br /&gt;
						}&lt;br /&gt;
					} while (loop);&lt;br /&gt;
				} else {&lt;br /&gt;
					break;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			return str;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// the output of this function doesn&#039;t respect the FILO structure of HTML&lt;br /&gt;
		// but since most browsers can handle it I&#039;ll save myself the hassle&lt;br /&gt;
		function parse_inline_formatting(str) {&lt;br /&gt;
			let italic,&lt;br /&gt;
				bold,&lt;br /&gt;
				i,&lt;br /&gt;
				li,&lt;br /&gt;
				o = &#039;&#039;;&lt;br /&gt;
			while ((i = str.indexOf(&amp;quot;&#039;&#039;&amp;quot;, li)) + 1) {&lt;br /&gt;
				o += str.substring(li, i);&lt;br /&gt;
				li = i + 2;&lt;br /&gt;
				if (str.charAt(i + 2) == &amp;quot;&#039;&amp;quot;) {&lt;br /&gt;
					li++;&lt;br /&gt;
					bold = !bold;&lt;br /&gt;
					o += bold ? &#039;&amp;lt;b&amp;gt;&#039; : &#039;&amp;lt;/b&amp;gt;&#039;;&lt;br /&gt;
				} else {&lt;br /&gt;
					italic = !italic;&lt;br /&gt;
					o += italic ? &#039;&amp;lt;i&amp;gt;&#039; : &#039;&amp;lt;/i&amp;gt;&#039;;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return o + str.substr(li);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		function parse_inline_wiki(str) {&lt;br /&gt;
			str = parse_inline_images(str);&lt;br /&gt;
&lt;br /&gt;
			// math&lt;br /&gt;
			str = str.replace(/&amp;lt;(?:)math&amp;gt;(.*?)&amp;lt;\/math&amp;gt;/gi, &#039;&#039;);&lt;br /&gt;
&lt;br /&gt;
			// Build a Mediawiki-formatted date string&lt;br /&gt;
			let date = new Date();&lt;br /&gt;
			let minutes = date.getUTCMinutes();&lt;br /&gt;
			if (minutes &amp;lt; 10) {&lt;br /&gt;
				minutes = &#039;0&#039; + minutes;&lt;br /&gt;
			}&lt;br /&gt;
			date = f(&lt;br /&gt;
				&#039;?:?, ? ? ? (UTC)&#039;,&lt;br /&gt;
				date.getUTCHours(),&lt;br /&gt;
				minutes,&lt;br /&gt;
				date.getUTCDate(),&lt;br /&gt;
				Insta.conf.locale.months[date.getUTCMonth()],&lt;br /&gt;
				date.getUTCFullYear()&lt;br /&gt;
			);&lt;br /&gt;
&lt;br /&gt;
			// text formatting&lt;br /&gt;
			str =&lt;br /&gt;
				str&lt;br /&gt;
					// signatures&lt;br /&gt;
					.replace(/~{5}(?!~)/g, date)&lt;br /&gt;
					.replace(/~{4}(?!~)/g, Insta.conf.user.name + &#039; &#039; + date)&lt;br /&gt;
					.replace(/~{3}(?!~)/g, Insta.conf.user.name)&lt;br /&gt;
					// [[:Category:...]], [[:Image:...]], etc...&lt;br /&gt;
					.replace(&lt;br /&gt;
						RegExp(&lt;br /&gt;
							&#039;\\[\\[:((?:&#039; +&lt;br /&gt;
								Insta.conf.locale.category +&lt;br /&gt;
								&#039;|Image|File|&#039; +&lt;br /&gt;
								Insta.conf.locale.image +&lt;br /&gt;
								&#039;|&#039; +&lt;br /&gt;
								Insta.conf.wiki.interwiki +&lt;br /&gt;
								&#039;):[^|]*?)\\]\\](\\w*)&#039;,&lt;br /&gt;
							&#039;gi&#039;&lt;br /&gt;
						),&lt;br /&gt;
						($0, $1, $2) =&amp;gt; f(&lt;br /&gt;
								&amp;quot;&amp;lt;a href=&#039;?&#039;&amp;gt;?&amp;lt;/a&amp;gt;&amp;quot;,&lt;br /&gt;
								Insta.conf.paths.articles + htmlescape_attr($1),&lt;br /&gt;
								htmlescape_text($1) + htmlescape_text($2)&lt;br /&gt;
							)&lt;br /&gt;
					)&lt;br /&gt;
					// remove straight category and interwiki tags&lt;br /&gt;
					.replace(&lt;br /&gt;
						RegExp(&lt;br /&gt;
							&#039;\\[\\[(?:&#039; +&lt;br /&gt;
								Insta.conf.locale.category +&lt;br /&gt;
								&#039;|&#039; +&lt;br /&gt;
								Insta.conf.wiki.interwiki +&lt;br /&gt;
								&#039;):.*?\\]\\]&#039;,&lt;br /&gt;
							&#039;gi&#039;&lt;br /&gt;
						),&lt;br /&gt;
						&#039;&#039;&lt;br /&gt;
					)&lt;br /&gt;
					// [[:Category:...|Links]], [[:Image:...|Links]], etc...&lt;br /&gt;
					.replace(&lt;br /&gt;
						RegExp(&lt;br /&gt;
							&#039;\\[\\[:((?:&#039; +&lt;br /&gt;
								Insta.conf.locale.category +&lt;br /&gt;
								&#039;|Image|File|&#039; +&lt;br /&gt;
								Insta.conf.locale.image +&lt;br /&gt;
								&#039;|&#039; +&lt;br /&gt;
								Insta.conf.wiki.interwiki +&lt;br /&gt;
								&#039;):.*?)\\|([^\\]]+?)\\]\\](\\w*)&#039;,&lt;br /&gt;
							&#039;gi&#039;&lt;br /&gt;
						),&lt;br /&gt;
						($0, $1, $2, $3) =&amp;gt; f(&lt;br /&gt;
								&amp;quot;&amp;lt;a href=&#039;?&#039;&amp;gt;?&amp;lt;/a&amp;gt;&amp;quot;,&lt;br /&gt;
								Insta.conf.paths.articles + htmlescape_attr($1),&lt;br /&gt;
								htmlescape_text($2) + htmlescape_text($3)&lt;br /&gt;
							)&lt;br /&gt;
					)&lt;br /&gt;
					// [[/Relative links]]&lt;br /&gt;
					.replace(/\[\[(\/[^|]*?)\]\]/g, ($0, $1) =&amp;gt; f(&lt;br /&gt;
							&amp;quot;&amp;lt;a href=&#039;?&#039;&amp;gt;?&amp;lt;/a&amp;gt;&amp;quot;,&lt;br /&gt;
							Insta.conf.baseUrl + htmlescape_attr($1),&lt;br /&gt;
							htmlescape_text($1)&lt;br /&gt;
						))&lt;br /&gt;
					// [[/Replaced|Relative links]]&lt;br /&gt;
					.replace(/\[\[(\/.*?)\|(.+?)\]\]/g, ($0, $1, $2) =&amp;gt; f(&lt;br /&gt;
							&amp;quot;&amp;lt;a href=&#039;?&#039;&amp;gt;?&amp;lt;/a&amp;gt;&amp;quot;,&lt;br /&gt;
							Insta.conf.baseUrl + htmlescape_attr($1),&lt;br /&gt;
							htmlescape_text($2)&lt;br /&gt;
						))&lt;br /&gt;
					// [[Common links]]&lt;br /&gt;
					.replace(/\[\[([^[|]*?)\]\](\w*)/g, ($0, $1, $2) =&amp;gt; f(&lt;br /&gt;
							&amp;quot;&amp;lt;a href=&#039;?&#039;&amp;gt;?&amp;lt;/a&amp;gt;&amp;quot;,&lt;br /&gt;
							Insta.conf.paths.articles + htmlescape_attr($1),&lt;br /&gt;
							htmlescape_text($1) + htmlescape_text($2)&lt;br /&gt;
						))&lt;br /&gt;
					// [[Replaced|Links]]&lt;br /&gt;
					.replace(/\[\[([^[]*?)\|([^\]]+?)\]\](\w*)/g, ($0, $1, $2, $3) =&amp;gt; f(&lt;br /&gt;
							&amp;quot;&amp;lt;a href=&#039;?&#039;&amp;gt;?&amp;lt;/a&amp;gt;&amp;quot;,&lt;br /&gt;
							Insta.conf.paths.articles + htmlescape_attr($1),&lt;br /&gt;
							htmlescape_text($2) + htmlescape_text($3)&lt;br /&gt;
						))&lt;br /&gt;
					// [[Stripped:Namespace|Namespace]]&lt;br /&gt;
					.replace(/\[\[([^\]]*?:)?(.*?)( *\(.*?\))?\|\]\]/g, ($0, $1, $2, $3) =&amp;gt; f(&lt;br /&gt;
							&amp;quot;&amp;lt;a href=&#039;?&#039;&amp;gt;?&amp;lt;/a&amp;gt;&amp;quot;,&lt;br /&gt;
							Insta.conf.paths.articles +&lt;br /&gt;
								htmlescape_attr($1) +&lt;br /&gt;
								htmlescape_attr($2) +&lt;br /&gt;
								htmlescape_attr($3),&lt;br /&gt;
							htmlescape_text($2)&lt;br /&gt;
						))&lt;br /&gt;
					// External links&lt;br /&gt;
					.replace(&lt;br /&gt;
						/\[(https?|news|ftp|mailto|gopher|irc):(\/*)([^\]]*?) (.*?)\]/g,&lt;br /&gt;
						($0, $1, $2, $3, $4) =&amp;gt; f(&lt;br /&gt;
								&amp;quot;&amp;lt;a class=&#039;external&#039; href=&#039;?:?&#039;&amp;gt;?&amp;lt;/a&amp;gt;&amp;quot;,&lt;br /&gt;
								htmlescape_attr($1),&lt;br /&gt;
								htmlescape_attr($2) + htmlescape_attr($3),&lt;br /&gt;
								htmlescape_text($4)&lt;br /&gt;
							)&lt;br /&gt;
					)&lt;br /&gt;
					.replace(/\[http:\/\/(.*?)\]/g, ($0, $1) =&amp;gt; f(&amp;quot;&amp;lt;a class=&#039;external&#039; href=&#039;http://?&#039;&amp;gt;[#]&amp;lt;/a&amp;gt;&amp;quot;, htmlescape_attr($1)))&lt;br /&gt;
					.replace(/\[(news|ftp|mailto|gopher|irc):(\/*)(.*?)\]/g, ($0, $1, $2, $3) =&amp;gt; f(&lt;br /&gt;
							&amp;quot;&amp;lt;a class=&#039;external&#039; href=&#039;?:?&#039;&amp;gt;?:?&amp;lt;/a&amp;gt;&amp;quot;,&lt;br /&gt;
							htmlescape_attr($1),&lt;br /&gt;
							htmlescape_attr($2) + htmlescape_attr($3),&lt;br /&gt;
							htmlescape_text($1),&lt;br /&gt;
							htmlescape_text($2) + htmlescape_text($3)&lt;br /&gt;
						))&lt;br /&gt;
					.replace(&lt;br /&gt;
						/(^| )(https?|news|ftp|mailto|gopher|irc):(\/*)([^ $]*[^.,!?;: $])/g,&lt;br /&gt;
						($0, $1, $2, $3, $4) =&amp;gt; f(&lt;br /&gt;
								&amp;quot;?&amp;lt;a class=&#039;external&#039; href=&#039;?:?&#039;&amp;gt;?:?&amp;lt;/a&amp;gt;&amp;quot;,&lt;br /&gt;
								htmlescape_text($1),&lt;br /&gt;
								htmlescape_attr($2),&lt;br /&gt;
								htmlescape_attr($3) + htmlescape_attr($4),&lt;br /&gt;
								htmlescape_text($2),&lt;br /&gt;
								htmlescape_text($3) + htmlescape_text($4)&lt;br /&gt;
							)&lt;br /&gt;
					)&lt;br /&gt;
					.replace(&#039;__NOTOC__&#039;, &#039;&#039;)&lt;br /&gt;
					.replace(&#039;__NOINDEX__&#039;, &#039;&#039;)&lt;br /&gt;
					.replace(&#039;__INDEX__&#039;, &#039;&#039;)&lt;br /&gt;
					.replace(&#039;__NOEDITSECTION__&#039;, &#039;&#039;);&lt;br /&gt;
			return parse_inline_formatting(str);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// begin parsing&lt;br /&gt;
		for (; remain(); ) {&lt;br /&gt;
			if (compareLineStringOrReg(/^(={1,6})(.*)\1(.*)$/)) {&lt;br /&gt;
				p = 0;&lt;br /&gt;
				endl(f(&#039;&amp;lt;h?&amp;gt;?&amp;lt;/h?&amp;gt;?&#039;, r[1].length, parse_inline_nowiki(r[2]), r[1].length, r[3]));&lt;br /&gt;
			} else if (compareLineStringOrReg(/^[*#:;]/)) {&lt;br /&gt;
				p = 0;&lt;br /&gt;
				parse_list();&lt;br /&gt;
			} else if (compareLineStringOrReg(&#039; &#039;)) {&lt;br /&gt;
				p = 0;&lt;br /&gt;
				parse_pre();&lt;br /&gt;
			} else if (compareLineStringOrReg(&#039;{|&#039;)) {&lt;br /&gt;
				p = 0;&lt;br /&gt;
				parse_table();&lt;br /&gt;
			} else if (compareLineStringOrReg(/^----+$/)) {&lt;br /&gt;
				p = 0;&lt;br /&gt;
				endl(&#039;&amp;lt;hr /&amp;gt;&#039;);&lt;br /&gt;
			} else if (compareLineStringOrReg(Insta.BLOCK_IMAGE)) {&lt;br /&gt;
				p = 0;&lt;br /&gt;
				parse_block_image();&lt;br /&gt;
			} else {&lt;br /&gt;
				// handle paragraphs&lt;br /&gt;
				if (compareLineString(&#039;&#039;)) {&lt;br /&gt;
					p = remain() &amp;gt; 1 &amp;amp;&amp;amp; ll[1] === &#039;&#039;;&lt;br /&gt;
					if (p) {&lt;br /&gt;
						endl(&#039;&amp;lt;p&amp;gt;&amp;lt;br&amp;gt;&#039;);&lt;br /&gt;
					}&lt;br /&gt;
				} else {&lt;br /&gt;
					if (!p) {&lt;br /&gt;
						ps(&#039;&amp;lt;p&amp;gt;&#039;);&lt;br /&gt;
						p = 1;&lt;br /&gt;
					}&lt;br /&gt;
					ps(parse_inline_nowiki(ll[0]) + &#039; &#039;);&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				sh();&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		return o;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function wiki2html(txt, baseurl) {&lt;br /&gt;
		Insta.conf.baseUrl = baseurl;&lt;br /&gt;
		return Insta.convert(txt);&lt;br /&gt;
	}&lt;br /&gt;
	// ENDFILE: livepreview.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: pageinfo.js&lt;br /&gt;
	function popupFilterPageSize(data) {&lt;br /&gt;
		return formatBytes(data.length);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function popupFilterCountLinks(data) {&lt;br /&gt;
		const num = countLinks(data);&lt;br /&gt;
		return String(num) + &#039;&amp;amp;nbsp;&#039; + (num != 1 ? popupString(&#039;wikiLinks&#039;) : popupString(&#039;wikiLink&#039;));&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function popupFilterCountImages(data) {&lt;br /&gt;
		const num = countImages(data);&lt;br /&gt;
		return String(num) + &#039;&amp;amp;nbsp;&#039; + (num != 1 ? popupString(&#039;images&#039;) : popupString(&#039;image&#039;));&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function popupFilterCountCategories(data) {&lt;br /&gt;
		const num = countCategories(data);&lt;br /&gt;
		return (&lt;br /&gt;
			String(num) + &#039;&amp;amp;nbsp;&#039; + (num != 1 ? popupString(&#039;categories&#039;) : popupString(&#039;category&#039;))&lt;br /&gt;
		);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function popupFilterLastModified(data, download) {&lt;br /&gt;
		const lastmod = download.lastModified;&lt;br /&gt;
		const now = new Date();&lt;br /&gt;
		const age = now - lastmod;&lt;br /&gt;
		if (lastmod &amp;amp;&amp;amp; getValueOf(&#039;popupLastModified&#039;)) {&lt;br /&gt;
			return tprintf(&#039;%s old&#039;, [formatAge(age)]).replace(/ /g, &#039;&amp;amp;nbsp;&#039;);&lt;br /&gt;
		}&lt;br /&gt;
		return &#039;&#039;;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function popupFilterWikibaseItem(data, download) {&lt;br /&gt;
		return download.wikibaseItem ?&lt;br /&gt;
			tprintf(&#039;&amp;lt;a href=&amp;quot;%s&amp;quot;&amp;gt;%s&amp;lt;/a&amp;gt;&#039;, [&lt;br /&gt;
				download.wikibaseRepo.replace(/\$1/g, download.wikibaseItem),&lt;br /&gt;
				download.wikibaseItem,&lt;br /&gt;
			]) :&lt;br /&gt;
			&#039;&#039;;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function formatAge(age) {&lt;br /&gt;
		// coerce into a number&lt;br /&gt;
		let a = 0 + age,&lt;br /&gt;
			aa = a;&lt;br /&gt;
&lt;br /&gt;
		const seclen = 1000;&lt;br /&gt;
		const minlen = 60 * seclen;&lt;br /&gt;
		const hourlen = 60 * minlen;&lt;br /&gt;
		const daylen = 24 * hourlen;&lt;br /&gt;
		const weeklen = 7 * daylen;&lt;br /&gt;
&lt;br /&gt;
		const numweeks = (a - (a % weeklen)) / weeklen;&lt;br /&gt;
		a = a - numweeks * weeklen;&lt;br /&gt;
		const sweeks = addunit(numweeks, &#039;week&#039;);&lt;br /&gt;
		const numdays = (a - (a % daylen)) / daylen;&lt;br /&gt;
		a = a - numdays * daylen;&lt;br /&gt;
		const sdays = addunit(numdays, &#039;day&#039;);&lt;br /&gt;
		const numhours = (a - (a % hourlen)) / hourlen;&lt;br /&gt;
		a = a - numhours * hourlen;&lt;br /&gt;
		const shours = addunit(numhours, &#039;hour&#039;);&lt;br /&gt;
		const nummins = (a - (a % minlen)) / minlen;&lt;br /&gt;
		a = a - nummins * minlen;&lt;br /&gt;
		const smins = addunit(nummins, &#039;minute&#039;);&lt;br /&gt;
		const numsecs = (a - (a % seclen)) / seclen;&lt;br /&gt;
		a = a - numsecs * seclen;&lt;br /&gt;
		const ssecs = addunit(numsecs, &#039;second&#039;);&lt;br /&gt;
&lt;br /&gt;
		if (aa &amp;gt; 4 * weeklen) {&lt;br /&gt;
			return sweeks;&lt;br /&gt;
		}&lt;br /&gt;
		if (aa &amp;gt; weeklen) {&lt;br /&gt;
			return sweeks + &#039; &#039; + sdays;&lt;br /&gt;
		}&lt;br /&gt;
		if (aa &amp;gt; daylen) {&lt;br /&gt;
			return sdays + &#039; &#039; + shours;&lt;br /&gt;
		}&lt;br /&gt;
		if (aa &amp;gt; 6 * hourlen) {&lt;br /&gt;
			return shours;&lt;br /&gt;
		}&lt;br /&gt;
		if (aa &amp;gt; hourlen) {&lt;br /&gt;
			return shours + &#039; &#039; + smins;&lt;br /&gt;
		}&lt;br /&gt;
		if (aa &amp;gt; 10 * minlen) {&lt;br /&gt;
			return smins;&lt;br /&gt;
		}&lt;br /&gt;
		if (aa &amp;gt; minlen) {&lt;br /&gt;
			return smins + &#039; &#039; + ssecs;&lt;br /&gt;
		}&lt;br /&gt;
		return ssecs;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function addunit(num, str) {&lt;br /&gt;
		return String(num) + &#039; &#039; + (num != 1 ? popupString(str + &#039;s&#039;) : popupString(str));&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function runPopupFilters(list, data, download) {&lt;br /&gt;
		const ret = [];&lt;br /&gt;
		for (let i = 0; i &amp;lt; list.length; ++i) {&lt;br /&gt;
			if (list[i] &amp;amp;&amp;amp; typeof list[i] == &#039;function&#039;) {&lt;br /&gt;
				const s = list[i](data, download, download.owner.article);&lt;br /&gt;
				if (s) {&lt;br /&gt;
					ret.push(s);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return ret;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function getPageInfo(data, download) {&lt;br /&gt;
		if (!data || data.length === 0) {&lt;br /&gt;
			return popupString(&#039;Empty page&#039;);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const popupFilters = getValueOf(&#039;popupFilters&#039;) || [];&lt;br /&gt;
		const extraPopupFilters = getValueOf(&#039;extraPopupFilters&#039;) || [];&lt;br /&gt;
		const pageInfoArray = runPopupFilters(popupFilters.concat(extraPopupFilters), data, download);&lt;br /&gt;
&lt;br /&gt;
		let pageInfo = pageInfoArray.join(&#039;, &#039;);&lt;br /&gt;
		if (pageInfo !== &#039;&#039;) {&lt;br /&gt;
			pageInfo = upcaseFirst(pageInfo);&lt;br /&gt;
		}&lt;br /&gt;
		return pageInfo;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// this could be improved!&lt;br /&gt;
	function countLinks(wikiText) {&lt;br /&gt;
		return wikiText.split(&#039;[[&#039;).length - 1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// if N = # matches, n = # brackets, then&lt;br /&gt;
	// String.parenSplit(regex) intersperses the N+1 split elements&lt;br /&gt;
	// with Nn other elements. So total length is&lt;br /&gt;
	// L= N+1 + Nn = N(n+1)+1. So N=(L-1)/(n+1).&lt;br /&gt;
&lt;br /&gt;
	function countImages(wikiText) {&lt;br /&gt;
		return (wikiText.parenSplit(pg.re.image).length - 1) / (pg.re.imageBracketCount + 1);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function countCategories(wikiText) {&lt;br /&gt;
		return (wikiText.parenSplit(pg.re.category).length - 1) / (pg.re.categoryBracketCount + 1);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function popupFilterStubDetect(data, download, article) {&lt;br /&gt;
		const counts = stubCount(data, article);&lt;br /&gt;
		if (counts.real) {&lt;br /&gt;
			return popupString(&#039;stub&#039;);&lt;br /&gt;
		}&lt;br /&gt;
		if (counts.sect) {&lt;br /&gt;
			return popupString(&#039;section stub&#039;);&lt;br /&gt;
		}&lt;br /&gt;
		return &#039;&#039;;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function popupFilterDisambigDetect(data, download, article) {&lt;br /&gt;
		if (!getValueOf(&#039;popupAllDabsStubs&#039;) &amp;amp;&amp;amp; article.namespace()) {&lt;br /&gt;
			return &#039;&#039;;&lt;br /&gt;
		}&lt;br /&gt;
		return isDisambig(data, article) ? popupString(&#039;disambig&#039;) : &#039;&#039;;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function formatBytes(num) {&lt;br /&gt;
		return num &amp;gt; 949 ?&lt;br /&gt;
			Math.round(num / 100) / 10 + popupString(&#039;kB&#039;) :&lt;br /&gt;
			num + &#039;&amp;amp;nbsp;&#039; + popupString(&#039;bytes&#039;);&lt;br /&gt;
	}&lt;br /&gt;
	// ENDFILE: pageinfo.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: titles.js&lt;br /&gt;
	/**&lt;br /&gt;
	 * @file Defines the {@link Title} class, and associated crufty functions.&lt;br /&gt;
	 *&lt;br /&gt;
	 * &amp;lt;code&amp;gt;Title&amp;lt;/code&amp;gt; deals with article titles and their various&lt;br /&gt;
	 * forms.  {@link Stringwrapper} is the parent class of&lt;br /&gt;
	 * &amp;lt;code&amp;gt;Title&amp;lt;/code&amp;gt;, which exists simply to make things a little&lt;br /&gt;
	 * neater.&lt;br /&gt;
	 */&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Creates a new Stringwrapper.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @constructor&lt;br /&gt;
	 *&lt;br /&gt;
	 * @class the Stringwrapper class. This base class is not really&lt;br /&gt;
	 * useful on its own; it just wraps various common string operations.&lt;br /&gt;
	 */&lt;br /&gt;
	function Stringwrapper() {&lt;br /&gt;
		/**&lt;br /&gt;
		 * Wrapper for this.toString().indexOf()&lt;br /&gt;
		 *&lt;br /&gt;
		 * @param {string} x&lt;br /&gt;
		 * @type {number}&lt;br /&gt;
		 */&lt;br /&gt;
		this.indexOf = function (x) {&lt;br /&gt;
			return this.toString().indexOf(x);&lt;br /&gt;
		};&lt;br /&gt;
		/**&lt;br /&gt;
		 * Returns this.value.&lt;br /&gt;
		 *&lt;br /&gt;
		 * @type {string}&lt;br /&gt;
		 */&lt;br /&gt;
		this.toString = function () {&lt;br /&gt;
			return this.value;&lt;br /&gt;
		};&lt;br /&gt;
		/**&lt;br /&gt;
		 * Wrapper for {@link String#parenSplit} applied to this.toString()&lt;br /&gt;
		 *&lt;br /&gt;
		 * @param {RegExp} x&lt;br /&gt;
		 * @type {Array}&lt;br /&gt;
		 */&lt;br /&gt;
		this.parenSplit = function (x) {&lt;br /&gt;
			return this.toString().parenSplit(x);&lt;br /&gt;
		};&lt;br /&gt;
		/**&lt;br /&gt;
		 * Wrapper for this.toString().substring()&lt;br /&gt;
		 *&lt;br /&gt;
		 * @param {string} x&lt;br /&gt;
		 * @param {string} y (optional)&lt;br /&gt;
		 * @type {string}&lt;br /&gt;
		 */&lt;br /&gt;
		this.substring = function (x, y) {&lt;br /&gt;
			if (typeof y == &#039;undefined&#039;) {&lt;br /&gt;
				return this.toString().substring(x);&lt;br /&gt;
			}&lt;br /&gt;
			return this.toString().substring(x, y);&lt;br /&gt;
		};&lt;br /&gt;
		/**&lt;br /&gt;
		 * Wrapper for this.toString().split()&lt;br /&gt;
		 *&lt;br /&gt;
		 * @param {string} x&lt;br /&gt;
		 * @type {Array}&lt;br /&gt;
		 */&lt;br /&gt;
		this.split = function (x) {&lt;br /&gt;
			return this.toString().split(x);&lt;br /&gt;
		};&lt;br /&gt;
		/**&lt;br /&gt;
		 * Wrapper for this.toString().replace()&lt;br /&gt;
		 *&lt;br /&gt;
		 * @param {string} x&lt;br /&gt;
		 * @param {string} y&lt;br /&gt;
		 * @type {string}&lt;br /&gt;
		 */&lt;br /&gt;
		this.replace = function (x, y) {&lt;br /&gt;
			return this.toString().replace(x, y);&lt;br /&gt;
		};&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Creates a new &amp;lt;code&amp;gt;Title&amp;lt;/code&amp;gt;.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @constructor&lt;br /&gt;
	 *&lt;br /&gt;
	 * @class The Title class. Holds article titles and converts them into&lt;br /&gt;
	 * various forms. Also deals with anchors, by which we mean the bits&lt;br /&gt;
	 * of the article URL after a # character, representing locations&lt;br /&gt;
	 * within an article.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param {string} value The initial value to assign to the&lt;br /&gt;
	 * article. This must be the canonical title (see {@link&lt;br /&gt;
	 * Title#value}. Omit this in the constructor and use another function&lt;br /&gt;
	 * to set the title if this is unavailable.&lt;br /&gt;
	 */&lt;br /&gt;
	function Title(val) {&lt;br /&gt;
		/**&lt;br /&gt;
		 * The canonical article title. This must be in UTF-8 with no&lt;br /&gt;
		 * entities, escaping or nasties. Also, underscores should be&lt;br /&gt;
		 * replaced with spaces.&lt;br /&gt;
		 *&lt;br /&gt;
		 * @type {string}&lt;br /&gt;
		 * @private&lt;br /&gt;
		 */&lt;br /&gt;
		this.value = null;&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
		 * The canonical form of the anchor. This should be exactly as&lt;br /&gt;
		 * it appears in the URL, i.e. with the .C3.0A bits in.&lt;br /&gt;
		 *&lt;br /&gt;
		 * @type {string}&lt;br /&gt;
		 */&lt;br /&gt;
		this.anchor = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
		this.setUtf(val);&lt;br /&gt;
	}&lt;br /&gt;
	Title.prototype = new Stringwrapper();&lt;br /&gt;
	/**&lt;br /&gt;
	 * Returns the canonical representation of the article title, optionally without anchor.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param {boolean} omitAnchor&lt;br /&gt;
	 * @fixme Decide specs for anchor&lt;br /&gt;
	 * @return String The article title and the anchor.&lt;br /&gt;
	 */&lt;br /&gt;
	Title.prototype.toString = function (omitAnchor) {&lt;br /&gt;
		return this.value + (!omitAnchor &amp;amp;&amp;amp; this.anchor ? &#039;#&#039; + this.anchorString() : &#039;&#039;);&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.anchorString = function () {&lt;br /&gt;
		if (!this.anchor) {&lt;br /&gt;
			return &#039;&#039;;&lt;br /&gt;
		}&lt;br /&gt;
		const split = this.anchor.parenSplit(/((?:[.][0-9A-F]{2})+)/);&lt;br /&gt;
		const len = split.length;&lt;br /&gt;
		let value;&lt;br /&gt;
		for (let j = 1; j &amp;lt; len; j += 2) {&lt;br /&gt;
			// FIXME s/decodeURI/decodeURIComponent/g ?&lt;br /&gt;
			value = split[j].split(&#039;.&#039;).join(&#039;%&#039;);&lt;br /&gt;
			try {&lt;br /&gt;
				value = decodeURIComponent(value);&lt;br /&gt;
			} catch (e) {&lt;br /&gt;
				// cannot decode&lt;br /&gt;
			}&lt;br /&gt;
			split[j] = value.split(&#039;_&#039;).join(&#039; &#039;);&lt;br /&gt;
		}&lt;br /&gt;
		return split.join(&#039;&#039;);&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.urlAnchor = function () {&lt;br /&gt;
		const split = this.anchor.parenSplit(&#039;/((?:[%][0-9A-F]{2})+)/&#039;);&lt;br /&gt;
		const len = split.length;&lt;br /&gt;
		for (let j = 1; j &amp;lt; len; j += 2) {&lt;br /&gt;
			split[j] = split[j].split(&#039;%&#039;).join(&#039;.&#039;);&lt;br /&gt;
		}&lt;br /&gt;
		return split.join(&#039;&#039;);&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.anchorFromUtf = function (str) {&lt;br /&gt;
		this.anchor = encodeURIComponent(str.split(&#039; &#039;).join(&#039;_&#039;))&lt;br /&gt;
			.split(&#039;%3A&#039;)&lt;br /&gt;
			.join(&#039;:&#039;)&lt;br /&gt;
			.split(&amp;quot;&#039;&amp;quot;)&lt;br /&gt;
			.join(&#039;%27&#039;)&lt;br /&gt;
			.split(&#039;%&#039;)&lt;br /&gt;
			.join(&#039;.&#039;);&lt;br /&gt;
	};&lt;br /&gt;
	Title.fromURL = function (h) {&lt;br /&gt;
		return new Title().fromURL(h);&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.fromURL = function (h) {&lt;br /&gt;
		if (typeof h != &#039;string&#039;) {&lt;br /&gt;
			this.value = null;&lt;br /&gt;
			return this;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// NOTE : playing with decodeURI, encodeURI, escape, unescape,&lt;br /&gt;
		// we seem to be able to replicate the IE borked encoding&lt;br /&gt;
&lt;br /&gt;
		// IE doesn&#039;t do this new-fangled utf-8 thing.&lt;br /&gt;
		// and it&#039;s worse than that.&lt;br /&gt;
		// IE seems to treat the query string differently to the rest of the url&lt;br /&gt;
		// the query is treated as bona-fide utf8, but the first bit of the url is pissed around with&lt;br /&gt;
&lt;br /&gt;
		// we fix up &amp;amp; for all browsers, just in case.&lt;br /&gt;
		const splitted = h.split(&#039;?&#039;);&lt;br /&gt;
		splitted[0] = splitted[0].split(&#039;&amp;amp;&#039;).join(&#039;%26&#039;);&lt;br /&gt;
&lt;br /&gt;
		h = splitted.join(&#039;?&#039;);&lt;br /&gt;
&lt;br /&gt;
		const contribs = pg.re.contribs.exec(h);&lt;br /&gt;
		if (contribs) {&lt;br /&gt;
			if (contribs[1] == &#039;title=&#039;) {&lt;br /&gt;
				contribs[3] = contribs[3].split(&#039;+&#039;).join(&#039; &#039;);&lt;br /&gt;
			}&lt;br /&gt;
			const u = new Title(contribs[3]);&lt;br /&gt;
			this.setUtf(&lt;br /&gt;
				this.decodeNasties(&lt;br /&gt;
					mw.config.get(&#039;wgFormattedNamespaces&#039;)[pg.nsUserId] + &#039;:&#039; + u.stripNamespace()&lt;br /&gt;
				)&lt;br /&gt;
			);&lt;br /&gt;
			return this;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const email = pg.re.email.exec(h);&lt;br /&gt;
		if (email) {&lt;br /&gt;
			this.setUtf(&lt;br /&gt;
				this.decodeNasties(&lt;br /&gt;
					mw.config.get(&#039;wgFormattedNamespaces&#039;)[pg.nsUserId] +&lt;br /&gt;
						&#039;:&#039; +&lt;br /&gt;
						new Title(email[3]).stripNamespace()&lt;br /&gt;
				)&lt;br /&gt;
			);&lt;br /&gt;
			return this;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const backlinks = pg.re.backlinks.exec(h);&lt;br /&gt;
		if (backlinks) {&lt;br /&gt;
			this.setUtf(this.decodeNasties(new Title(backlinks[3])));&lt;br /&gt;
			return this;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		//A dummy title object for a Special:Diff link.&lt;br /&gt;
		const specialdiff = pg.re.specialdiff.exec(h);&lt;br /&gt;
		if (specialdiff) {&lt;br /&gt;
			this.setUtf(&lt;br /&gt;
				this.decodeNasties(&lt;br /&gt;
					new Title(mw.config.get(&#039;wgFormattedNamespaces&#039;)[pg.nsSpecialId] + &#039;:Diff&#039;)&lt;br /&gt;
				)&lt;br /&gt;
			);&lt;br /&gt;
			return this;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// no more special cases to check --&lt;br /&gt;
		// hopefully it&#039;s not a disguised user-related or specially treated special page&lt;br /&gt;
		// Includes references&lt;br /&gt;
		const m = pg.re.main.exec(h);&lt;br /&gt;
		if (m === null) {&lt;br /&gt;
			this.value = null;&lt;br /&gt;
		} else {&lt;br /&gt;
			const fromBotInterface = /[?](.+[&amp;amp;])?title=/.test(h);&lt;br /&gt;
			if (fromBotInterface) {&lt;br /&gt;
				m[2] = m[2].split(&#039;+&#039;).join(&#039;_&#039;);&lt;br /&gt;
			}&lt;br /&gt;
			const extracted = m[2] + (m[3] ? &#039;#&#039; + m[3] : &#039;&#039;);&lt;br /&gt;
			if (pg.flag.isSafari &amp;amp;&amp;amp; /%25[0-9A-Fa-f]{2}/.test(extracted)) {&lt;br /&gt;
				// Fix Safari issue&lt;br /&gt;
				// Safari sometimes encodes % as %25 in UTF-8 encoded strings like %E5%A3 -&amp;gt; %25E5%25A3.&lt;br /&gt;
				this.setUtf(decodeURIComponent(unescape(extracted)));&lt;br /&gt;
			} else {&lt;br /&gt;
				this.setUtf(this.decodeNasties(extracted));&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return this;&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.decodeNasties = function (txt) {&lt;br /&gt;
		// myDecodeURI uses decodeExtras, which removes _,&lt;br /&gt;
		// thus ruining citations previews, which are formated as &amp;quot;cite_note-1&amp;quot;&lt;br /&gt;
		try {&lt;br /&gt;
			let ret = decodeURI(this.decodeEscapes(txt));&lt;br /&gt;
			ret = ret.replace(/[_ ]*$/, &#039;&#039;);&lt;br /&gt;
			return ret;&lt;br /&gt;
		} catch (e) {&lt;br /&gt;
			return txt; // cannot decode&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
	// Decode valid %-encodings, otherwise escape them&lt;br /&gt;
	Title.prototype.decodeEscapes = function (txt) {&lt;br /&gt;
		const split = txt.parenSplit(/((?:[%][0-9A-Fa-f]{2})+)/);&lt;br /&gt;
		const len = split.length;&lt;br /&gt;
		// No %-encoded items found, so replace the literal %&lt;br /&gt;
		if (len === 1) {&lt;br /&gt;
			return split[0].replace(/%(?![0-9a-fA-F][0-9a-fA-F])/g, &#039;%25&#039;);&lt;br /&gt;
		}&lt;br /&gt;
		for (let i = 1; i &amp;lt; len; i = i + 2) {&lt;br /&gt;
			split[i] = decodeURIComponent(split[i]);&lt;br /&gt;
		}&lt;br /&gt;
		return split.join(&#039;&#039;);&lt;br /&gt;
	};&lt;br /&gt;
	Title.fromAnchor = function (a) {&lt;br /&gt;
		return new Title().fromAnchor(a);&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.fromAnchor = function (a) {&lt;br /&gt;
		if (!a) {&lt;br /&gt;
			this.value = null;&lt;br /&gt;
			return this;&lt;br /&gt;
		}&lt;br /&gt;
		return this.fromURL(a.href);&lt;br /&gt;
	};&lt;br /&gt;
	Title.fromWikiText = function (txt) {&lt;br /&gt;
		return new Title().fromWikiText(txt);&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.fromWikiText = function (txt) {&lt;br /&gt;
		// FIXME - testing needed&lt;br /&gt;
		txt = myDecodeURI(txt);&lt;br /&gt;
		this.setUtf(txt);&lt;br /&gt;
		return this;&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.hintValue = function () {&lt;br /&gt;
		if (!this.value) {&lt;br /&gt;
			return &#039;&#039;;&lt;br /&gt;
		}&lt;br /&gt;
		return safeDecodeURI(this.value);&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.toUserName = function (withNs) {&lt;br /&gt;
		if (this.namespaceId() != pg.nsUserId &amp;amp;&amp;amp; this.namespaceId() != pg.nsUsertalkId) {&lt;br /&gt;
			this.value = null;&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		this.value =&lt;br /&gt;
			(withNs ? mw.config.get(&#039;wgFormattedNamespaces&#039;)[pg.nsUserId] + &#039;:&#039; : &#039;&#039;) +&lt;br /&gt;
			this.stripNamespace().split(&#039;/&#039;)[0];&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.userName = function (withNs) {&lt;br /&gt;
		const t = new Title(this.value);&lt;br /&gt;
		t.toUserName(withNs);&lt;br /&gt;
		if (t.value) {&lt;br /&gt;
			return t;&lt;br /&gt;
		}&lt;br /&gt;
		return null;&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.toTalkPage = function () {&lt;br /&gt;
		// convert article to a talk page, or if we can&#039;t, return null&lt;br /&gt;
		// In other words: return null if this ALREADY IS a talk page&lt;br /&gt;
		// and return the corresponding talk page otherwise&lt;br /&gt;
		//&lt;br /&gt;
		// Per https://www.mediawiki.org/wiki/Manual:Namespace#Subject_and_talk_namespaces&lt;br /&gt;
		// * All discussion namespaces have odd-integer indices&lt;br /&gt;
		// * The discussion namespace index for a specific namespace with index n is n + 1&lt;br /&gt;
		if (this.value === null) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const namespaceId = this.namespaceId();&lt;br /&gt;
		if (namespaceId &amp;gt;= 0 &amp;amp;&amp;amp; namespaceId % 2 === 0) {&lt;br /&gt;
			//non-special and subject namespace&lt;br /&gt;
			const localizedNamespace = mw.config.get(&#039;wgFormattedNamespaces&#039;)[namespaceId + 1];&lt;br /&gt;
			if (typeof localizedNamespace !== &#039;undefined&#039;) {&lt;br /&gt;
				if (localizedNamespace === &#039;&#039;) {&lt;br /&gt;
					this.value = this.stripNamespace();&lt;br /&gt;
				} else {&lt;br /&gt;
					this.value = localizedNamespace.split(&#039; &#039;).join(&#039;_&#039;) + &#039;:&#039; + this.stripNamespace();&lt;br /&gt;
				}&lt;br /&gt;
				return this.value;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		this.value = null;&lt;br /&gt;
		return null;&lt;br /&gt;
	};&lt;br /&gt;
	// Return canonical, localized namespace&lt;br /&gt;
	Title.prototype.namespace = function () {&lt;br /&gt;
		return mw.config.get(&#039;wgFormattedNamespaces&#039;)[this.namespaceId()];&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.namespaceId = function () {&lt;br /&gt;
		const n = this.value.indexOf(&#039;:&#039;);&lt;br /&gt;
		if (n &amp;lt; 0) {&lt;br /&gt;
			return 0;&lt;br /&gt;
		} //mainspace&lt;br /&gt;
		const namespaceId =&lt;br /&gt;
			mw.config.get(&#039;wgNamespaceIds&#039;)[&lt;br /&gt;
				this.value.substring(0, n).split(&#039; &#039;).join(&#039;_&#039;).toLowerCase()&lt;br /&gt;
			];&lt;br /&gt;
		if (typeof namespaceId == &#039;undefined&#039;) {&lt;br /&gt;
			return 0;&lt;br /&gt;
		} //mainspace&lt;br /&gt;
		return namespaceId;&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.talkPage = function () {&lt;br /&gt;
		const t = new Title(this.value);&lt;br /&gt;
		t.toTalkPage();&lt;br /&gt;
		if (t.value) {&lt;br /&gt;
			return t;&lt;br /&gt;
		}&lt;br /&gt;
		return null;&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.isTalkPage = function () {&lt;br /&gt;
		if (this.talkPage() === null) {&lt;br /&gt;
			return true;&lt;br /&gt;
		}&lt;br /&gt;
		return false;&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.toArticleFromTalkPage = function () {&lt;br /&gt;
		//largely copy/paste from toTalkPage above.&lt;br /&gt;
		if (this.value === null) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const namespaceId = this.namespaceId();&lt;br /&gt;
		if (namespaceId &amp;gt;= 0 &amp;amp;&amp;amp; namespaceId % 2 == 1) {&lt;br /&gt;
			//non-special and talk namespace&lt;br /&gt;
			const localizedNamespace = mw.config.get(&#039;wgFormattedNamespaces&#039;)[namespaceId - 1];&lt;br /&gt;
			if (typeof localizedNamespace !== &#039;undefined&#039;) {&lt;br /&gt;
				if (localizedNamespace === &#039;&#039;) {&lt;br /&gt;
					this.value = this.stripNamespace();&lt;br /&gt;
				} else {&lt;br /&gt;
					this.value = localizedNamespace.split(&#039; &#039;).join(&#039;_&#039;) + &#039;:&#039; + this.stripNamespace();&lt;br /&gt;
				}&lt;br /&gt;
				return this.value;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		this.value = null;&lt;br /&gt;
		return null;&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.articleFromTalkPage = function () {&lt;br /&gt;
		const t = new Title(this.value);&lt;br /&gt;
		t.toArticleFromTalkPage();&lt;br /&gt;
		if (t.value) {&lt;br /&gt;
			return t;&lt;br /&gt;
		}&lt;br /&gt;
		return null;&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.articleFromTalkOrArticle = function () {&lt;br /&gt;
		const t = new Title(this.value);&lt;br /&gt;
		if (t.toArticleFromTalkPage()) {&lt;br /&gt;
			return t;&lt;br /&gt;
		}&lt;br /&gt;
		return this;&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.isIpUser = function () {&lt;br /&gt;
		return pg.re.ipUser.test(this.userName());&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.stripNamespace = function () {&lt;br /&gt;
		// returns a string, not a Title&lt;br /&gt;
		const n = this.value.indexOf(&#039;:&#039;);&lt;br /&gt;
		if (n &amp;lt; 0) {&lt;br /&gt;
			return this.value;&lt;br /&gt;
		}&lt;br /&gt;
		const namespaceId = this.namespaceId();&lt;br /&gt;
		if (namespaceId === pg.nsMainspaceId) {&lt;br /&gt;
			return this.value;&lt;br /&gt;
		}&lt;br /&gt;
		return this.value.substring(n + 1);&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.setUtf = function (value) {&lt;br /&gt;
		if (!value) {&lt;br /&gt;
			this.value = &#039;&#039;;&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		const anch = value.indexOf(&#039;#&#039;);&lt;br /&gt;
		if (anch &amp;lt; 0) {&lt;br /&gt;
			this.value = value.split(&#039;_&#039;).join(&#039; &#039;);&lt;br /&gt;
			this.anchor = &#039;&#039;;&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		this.value = value.substring(0, anch).split(&#039;_&#039;).join(&#039; &#039;);&lt;br /&gt;
		this.anchor = value.substring(anch + 1);&lt;br /&gt;
		this.ns = null; // wait until namespace() is called&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.setUrl = function (urlfrag) {&lt;br /&gt;
		const anch = urlfrag.indexOf(&#039;#&#039;);&lt;br /&gt;
		this.value = safeDecodeURI(urlfrag.substring(0, anch));&lt;br /&gt;
		this.anchor = this.value.substring(anch + 1);&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.append = function (x) {&lt;br /&gt;
		this.setUtf(this.value + x);&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.urlString = function (x) {&lt;br /&gt;
		if (!x) {&lt;br /&gt;
			x = {};&lt;br /&gt;
		}&lt;br /&gt;
		let v = this.toString(true);&lt;br /&gt;
		if (!x.omitAnchor &amp;amp;&amp;amp; this.anchor) {&lt;br /&gt;
			v += &#039;#&#039; + this.urlAnchor();&lt;br /&gt;
		}&lt;br /&gt;
		if (!x.keepSpaces) {&lt;br /&gt;
			v = v.split(&#039; &#039;).join(&#039;_&#039;);&lt;br /&gt;
		}&lt;br /&gt;
		return encodeURI(v).split(&#039;&amp;amp;&#039;).join(&#039;%26&#039;).split(&#039;?&#039;).join(&#039;%3F&#039;).split(&#039;+&#039;).join(&#039;%2B&#039;);&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.removeAnchor = function () {&lt;br /&gt;
		return new Title(this.toString(true));&lt;br /&gt;
	};&lt;br /&gt;
	Title.prototype.toUrl = function () {&lt;br /&gt;
		return pg.wiki.titlebase + this.urlString();&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function parseParams(url) {&lt;br /&gt;
		const specialDiff = pg.re.specialdiff.exec(url);&lt;br /&gt;
		if (specialDiff) {&lt;br /&gt;
			const split = specialDiff[1].split(&#039;/&#039;);&lt;br /&gt;
			if (split.length == 1) {&lt;br /&gt;
				return { oldid: split[0], diff: &#039;prev&#039; };&lt;br /&gt;
			} else if (split.length == 2) {&lt;br /&gt;
				return { oldid: split[0], diff: split[1] };&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const ret = {};&lt;br /&gt;
		if (url.indexOf(&#039;?&#039;) == -1) {&lt;br /&gt;
			return ret;&lt;br /&gt;
		}&lt;br /&gt;
		url = url.split(&#039;#&#039;)[0];&lt;br /&gt;
		const s = url.split(&#039;?&#039;).slice(1).join();&lt;br /&gt;
		const t = s.split(&#039;&amp;amp;&#039;);&lt;br /&gt;
		for (let i = 0; i &amp;lt; t.length; ++i) {&lt;br /&gt;
			const z = t[i].split(&#039;=&#039;);&lt;br /&gt;
			z.push(null);&lt;br /&gt;
			ret[z[0]] = z[1];&lt;br /&gt;
		}&lt;br /&gt;
		//Diff revision with no oldid is interpreted as a diff to the previous revision by MediaWiki&lt;br /&gt;
		if (ret.diff &amp;amp;&amp;amp; typeof ret.oldid === &#039;undefined&#039;) {&lt;br /&gt;
			ret.oldid = &#039;prev&#039;;&lt;br /&gt;
		}&lt;br /&gt;
		//Documentation seems to say something different, but oldid can also accept prev/next, and&lt;br /&gt;
		//Echo is emitting such URLs. Simple fixup during parameter decoding:&lt;br /&gt;
		if (ret.oldid &amp;amp;&amp;amp; (ret.oldid === &#039;prev&#039; || ret.oldid === &#039;next&#039; || ret.oldid === &#039;cur&#039;)) {&lt;br /&gt;
			const helper = ret.diff;&lt;br /&gt;
			ret.diff = ret.oldid;&lt;br /&gt;
			ret.oldid = helper;&lt;br /&gt;
		}&lt;br /&gt;
		return ret;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// (a) myDecodeURI (first standard decodeURI, then pg.re.urlNoPopup)&lt;br /&gt;
	// (b) change spaces to underscores&lt;br /&gt;
	// (c) encodeURI (just the straight one, no pg.re.urlNoPopup)&lt;br /&gt;
&lt;br /&gt;
	function myDecodeURI(str) {&lt;br /&gt;
		let ret;&lt;br /&gt;
		// FIXME decodeURIComponent??&lt;br /&gt;
		try {&lt;br /&gt;
			ret = decodeURI(str.toString());&lt;br /&gt;
		} catch (summat) {&lt;br /&gt;
			return str;&lt;br /&gt;
		}&lt;br /&gt;
		for (let i = 0; i &amp;lt; pg.misc.decodeExtras.length; ++i) {&lt;br /&gt;
			const from = pg.misc.decodeExtras[i].from;&lt;br /&gt;
			const to = pg.misc.decodeExtras[i].to;&lt;br /&gt;
			ret = ret.split(from).join(to);&lt;br /&gt;
		}&lt;br /&gt;
		return ret;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function safeDecodeURI(str) {&lt;br /&gt;
		const ret = myDecodeURI(str);&lt;br /&gt;
		return ret || str;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	///////////&lt;br /&gt;
	// TESTS //&lt;br /&gt;
	///////////&lt;br /&gt;
&lt;br /&gt;
	function isDisambig(data, article) {&lt;br /&gt;
		if (!getValueOf(&#039;popupAllDabsStubs&#039;) &amp;amp;&amp;amp; article.namespace()) {&lt;br /&gt;
			return false;&lt;br /&gt;
		}&lt;br /&gt;
		return !article.isTalkPage() &amp;amp;&amp;amp; pg.re.disambig.test(data);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function stubCount(data, article) {&lt;br /&gt;
		if (!getValueOf(&#039;popupAllDabsStubs&#039;) &amp;amp;&amp;amp; article.namespace()) {&lt;br /&gt;
			return false;&lt;br /&gt;
		}&lt;br /&gt;
		let sectStub = 0;&lt;br /&gt;
		let realStub = 0;&lt;br /&gt;
		if (pg.re.stub.test(data)) {&lt;br /&gt;
			const s = data.parenSplit(pg.re.stub);&lt;br /&gt;
			for (let i = 1; i &amp;lt; s.length; i = i + 2) {&lt;br /&gt;
				if (s[i]) {&lt;br /&gt;
					++sectStub;&lt;br /&gt;
				} else {&lt;br /&gt;
					++realStub;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return { real: realStub, sect: sectStub };&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function isValidImageName(str) {&lt;br /&gt;
		// extend as needed...&lt;br /&gt;
		return str.indexOf(&#039;{&#039;) == -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function isInStrippableNamespace(article) {&lt;br /&gt;
		// Does the namespace allow subpages&lt;br /&gt;
		// Note, would be better if we had access to wgNamespacesWithSubpages&lt;br /&gt;
		return article.namespaceId() !== 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function isInMainNamespace(article) {&lt;br /&gt;
		return article.namespaceId() === 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function anchorContainsImage(a) {&lt;br /&gt;
		// iterate over children of anchor a&lt;br /&gt;
		// see if any are images&lt;br /&gt;
		if (a === null) {&lt;br /&gt;
			return false;&lt;br /&gt;
		}&lt;br /&gt;
		const kids = a.childNodes;&lt;br /&gt;
		for (let i = 0; i &amp;lt; kids.length; ++i) {&lt;br /&gt;
			if (kids[i].nodeName == &#039;IMG&#039;) {&lt;br /&gt;
				return true;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return false;&lt;br /&gt;
	}&lt;br /&gt;
	function isPopupLink(a) {&lt;br /&gt;
		// NB for performance reasons, TOC links generally return true&lt;br /&gt;
		// they should be stripped out later&lt;br /&gt;
&lt;br /&gt;
		if (!markNopopupSpanLinks.done) {&lt;br /&gt;
			markNopopupSpanLinks();&lt;br /&gt;
		}&lt;br /&gt;
		if (a.inNopopupSpan) {&lt;br /&gt;
			return false;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// FIXME is this faster inline?&lt;br /&gt;
		if (a.onmousedown || a.getAttribute(&#039;nopopup&#039;)) {&lt;br /&gt;
			return false;&lt;br /&gt;
		}&lt;br /&gt;
		const h = a.href;&lt;br /&gt;
		if (h === document.location.href + &#039;#&#039;) {&lt;br /&gt;
			return false;&lt;br /&gt;
		}&lt;br /&gt;
		if (!pg.re.basenames.test(h)) {&lt;br /&gt;
			return false;&lt;br /&gt;
		}&lt;br /&gt;
		if (!pg.re.urlNoPopup.test(h)) {&lt;br /&gt;
			return true;&lt;br /&gt;
		}&lt;br /&gt;
		return (&lt;br /&gt;
			(pg.re.email.test(h) ||&lt;br /&gt;
				pg.re.contribs.test(h) ||&lt;br /&gt;
				pg.re.backlinks.test(h) ||&lt;br /&gt;
				pg.re.specialdiff.test(h)) &amp;amp;&amp;amp;&lt;br /&gt;
			h.indexOf(&#039;&amp;amp;limit=&#039;) == -1&lt;br /&gt;
		);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function markNopopupSpanLinks() {&lt;br /&gt;
		if (!getValueOf(&#039;popupOnlyArticleLinks&#039;)) {&lt;br /&gt;
			fixVectorMenuPopups();&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const s = $(&#039;.nopopups&#039;).toArray();&lt;br /&gt;
		for (let i = 0; i &amp;lt; s.length; ++i) {&lt;br /&gt;
			const as = s[i].getElementsByTagName(&#039;a&#039;);&lt;br /&gt;
			for (let j = 0; j &amp;lt; as.length; ++j) {&lt;br /&gt;
				as[j].inNopopupSpan = true;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		markNopopupSpanLinks.done = true;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function fixVectorMenuPopups() {&lt;br /&gt;
		$(&#039;nav.vector-menu h3:first a:first&#039;).prop(&#039;inNopopupSpan&#039;, true);&lt;br /&gt;
	}&lt;br /&gt;
	// ENDFILE: titles.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: getpage.js&lt;br /&gt;
	//////////////////////////////////////////////////&lt;br /&gt;
	// Wiki-specific downloading&lt;br /&gt;
	//&lt;br /&gt;
&lt;br /&gt;
	// Schematic for a getWiki call&lt;br /&gt;
	//&lt;br /&gt;
	//             getPageWithCaching&lt;br /&gt;
	//					|&lt;br /&gt;
	//	   false		|		  true&lt;br /&gt;
	// getPage&amp;lt;-[findPictureInCache]-&amp;gt;-onComplete(a fake download)&lt;br /&gt;
	//   \.&lt;br /&gt;
	//	 (async)-&amp;gt;addPageToCache(download)-&amp;gt;-onComplete(download)&lt;br /&gt;
&lt;br /&gt;
	// check cache to see if page exists&lt;br /&gt;
&lt;br /&gt;
	function getPageWithCaching(url, onComplete, owner) {&lt;br /&gt;
		log(&#039;getPageWithCaching, url=&#039; + url);&lt;br /&gt;
		const i = findInPageCache(url);&lt;br /&gt;
		let d;&lt;br /&gt;
		if (i &amp;gt; -1) {&lt;br /&gt;
			d = fakeDownload(&lt;br /&gt;
				url,&lt;br /&gt;
				owner.idNumber,&lt;br /&gt;
				onComplete,&lt;br /&gt;
				pg.cache.pages[i].data,&lt;br /&gt;
				pg.cache.pages[i].lastModified,&lt;br /&gt;
				owner&lt;br /&gt;
			);&lt;br /&gt;
		} else {&lt;br /&gt;
			d = getPage(url, onComplete, owner);&lt;br /&gt;
			if (d &amp;amp;&amp;amp; owner &amp;amp;&amp;amp; owner.addDownload) {&lt;br /&gt;
				owner.addDownload(d);&lt;br /&gt;
				d.owner = owner;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function getPage(url, onComplete, owner) {&lt;br /&gt;
		log(&#039;getPage&#039;);&lt;br /&gt;
		const callback = function (d) {&lt;br /&gt;
			if (!d.aborted) {&lt;br /&gt;
				addPageToCache(d);&lt;br /&gt;
				onComplete(d);&lt;br /&gt;
			}&lt;br /&gt;
		};&lt;br /&gt;
		return startDownload(url, owner.idNumber, callback);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function findInPageCache(url) {&lt;br /&gt;
		for (let i = 0; i &amp;lt; pg.cache.pages.length; ++i) {&lt;br /&gt;
			if (url == pg.cache.pages[i].url) {&lt;br /&gt;
				return i;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function addPageToCache(download) {&lt;br /&gt;
		log(&#039;addPageToCache &#039; + download.url);&lt;br /&gt;
		const page = {&lt;br /&gt;
			url: download.url,&lt;br /&gt;
			data: download.data,&lt;br /&gt;
			lastModified: download.lastModified,&lt;br /&gt;
		};&lt;br /&gt;
		return pg.cache.pages.push(page);&lt;br /&gt;
	}&lt;br /&gt;
	// ENDFILE: getpage.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: parensplit.js&lt;br /&gt;
	//////////////////////////////////////////////////&lt;br /&gt;
	// parenSplit&lt;br /&gt;
&lt;br /&gt;
	// String.prototype.parenSplit should do what ECMAscript says String.prototype.split does,&lt;br /&gt;
	// interspersing paren matches (regex capturing groups) between the split elements.&lt;br /&gt;
	// i.e. &#039;abc&#039;.split(/(b)/)) should return [&#039;a&#039;,&#039;b&#039;,&#039;c&#039;], not [&#039;a&#039;,&#039;c&#039;]&lt;br /&gt;
&lt;br /&gt;
	if (String(&#039;abc&#039;.split(/(b)/)) != &#039;a,b,c&#039;) {&lt;br /&gt;
		// broken String.split, e.g. konq, IE &amp;lt; 10&lt;br /&gt;
		String.prototype.parenSplit = function (re) {&lt;br /&gt;
			re = nonGlobalRegex(re);&lt;br /&gt;
			let s = this;&lt;br /&gt;
			let m = re.exec(s);&lt;br /&gt;
			let ret = [];&lt;br /&gt;
			while (m &amp;amp;&amp;amp; s) {&lt;br /&gt;
				// without the following loop, we have&lt;br /&gt;
				// &#039;ab&#039;.parenSplit(/a|(b)/) != &#039;ab&#039;.split(/a|(b)/)&lt;br /&gt;
				for (let i = 0; i &amp;lt; m.length; ++i) {&lt;br /&gt;
					if (typeof m[i] == &#039;undefined&#039;) {&lt;br /&gt;
						m[i] = &#039;&#039;;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				ret.push(s.substring(0, m.index));&lt;br /&gt;
				ret = ret.concat(m.slice(1));&lt;br /&gt;
				s = s.substring(m.index + m[0].length);&lt;br /&gt;
				m = re.exec(s);&lt;br /&gt;
			}&lt;br /&gt;
			ret.push(s);&lt;br /&gt;
			return ret;&lt;br /&gt;
		};&lt;br /&gt;
	} else {&lt;br /&gt;
		String.prototype.parenSplit = function (re) {&lt;br /&gt;
			return this.split(re);&lt;br /&gt;
		};&lt;br /&gt;
		String.prototype.parenSplit.isNative = true;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function nonGlobalRegex(re) {&lt;br /&gt;
		const s = re.toString();&lt;br /&gt;
		let flags = &#039;&#039;;&lt;br /&gt;
		for (var j = s.length; s.charAt(j) != &#039;/&#039;; --j) {&lt;br /&gt;
			if (s.charAt(j) != &#039;g&#039;) {&lt;br /&gt;
				flags += s.charAt(j);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		const t = s.substring(1, j);&lt;br /&gt;
		return RegExp(t, flags);&lt;br /&gt;
	}&lt;br /&gt;
	// ENDFILE: parensplit.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: tools.js&lt;br /&gt;
	// IE madness with encoding&lt;br /&gt;
	// ========================&lt;br /&gt;
	//&lt;br /&gt;
	// suppose throughout that the page is in utf8, like wikipedia&lt;br /&gt;
	//&lt;br /&gt;
	// if a is an anchor DOM element and a.href should consist of&lt;br /&gt;
	//&lt;br /&gt;
	// http://host.name.here/wiki/foo?bar=baz&lt;br /&gt;
	//&lt;br /&gt;
	// then IE gives foo as &amp;quot;latin1-encoded&amp;quot; utf8; we have foo = decode_utf8(decodeURI(foo_ie))&lt;br /&gt;
	// but IE gives bar=baz correctly as plain utf8&lt;br /&gt;
	//&lt;br /&gt;
	// ---------------------------------&lt;br /&gt;
	//&lt;br /&gt;
	// IE&#039;s xmlhttp doesn&#039;t understand utf8 urls. Have to use encodeURI here.&lt;br /&gt;
	//&lt;br /&gt;
	// ---------------------------------&lt;br /&gt;
	//&lt;br /&gt;
	// summat else&lt;br /&gt;
&lt;br /&gt;
	// Source: http://aktuell.de.selfhtml.org/artikel/javascript/utf8b64/utf8.htm&lt;br /&gt;
&lt;br /&gt;
	function getJsObj(json) {&lt;br /&gt;
		try {&lt;br /&gt;
			const json_ret = JSON.parse(json);&lt;br /&gt;
			if (json_ret.warnings) {&lt;br /&gt;
				for (let w = 0; w &amp;lt; json_ret.warnings.length; w++) {&lt;br /&gt;
					if (json_ret.warnings[w][&#039;*&#039;]) {&lt;br /&gt;
						log(json_ret.warnings[w][&#039;*&#039;]);&lt;br /&gt;
					} else {&lt;br /&gt;
						log(json_ret.warnings[w].warnings);&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			} else if (json_ret.error) {&lt;br /&gt;
				errlog(json_ret.error.code + &#039;: &#039; + json_ret.error.info);&lt;br /&gt;
			}&lt;br /&gt;
			return json_ret;&lt;br /&gt;
		} catch (someError) {&lt;br /&gt;
			errlog(&#039;Something went wrong with getJsObj, json=&#039; + json);&lt;br /&gt;
			return 1;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function anyChild(obj) {&lt;br /&gt;
		for (const p in obj) {&lt;br /&gt;
			return obj[p];&lt;br /&gt;
		}&lt;br /&gt;
		return null;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function upcaseFirst(str) {&lt;br /&gt;
		if (typeof str != typeof &#039;&#039; || str === &#039;&#039;) {&lt;br /&gt;
			return &#039;&#039;;&lt;br /&gt;
		}&lt;br /&gt;
		return str.charAt(0).toUpperCase() + str.substring(1);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function findInArray(arr, foo) {&lt;br /&gt;
		if (!arr || !arr.length) {&lt;br /&gt;
			return -1;&lt;br /&gt;
		}&lt;br /&gt;
		const len = arr.length;&lt;br /&gt;
		for (let i = 0; i &amp;lt; len; ++i) {&lt;br /&gt;
			if (arr[i] == foo) {&lt;br /&gt;
				return i;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* eslint-disable no-unused-vars */&lt;br /&gt;
	function nextOne(array, value) {&lt;br /&gt;
		// NB if the array has two consecutive entries equal&lt;br /&gt;
		//	then this will loop on successive calls&lt;br /&gt;
		const i = findInArray(array, value);&lt;br /&gt;
		if (i &amp;lt; 0) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
		return array[i + 1];&lt;br /&gt;
	}&lt;br /&gt;
	/* eslint-enable no-unused-vars */&lt;br /&gt;
&lt;br /&gt;
	function literalizeRegex(str) {&lt;br /&gt;
		return mw.util.escapeRegExp(str);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	String.prototype.entify = function () {&lt;br /&gt;
		//var shy=&#039;&amp;amp;shy;&#039;;&lt;br /&gt;
		return this.split(&#039;&amp;amp;&#039;)&lt;br /&gt;
			.join(&#039;&amp;amp;amp;&#039;)&lt;br /&gt;
			.split(&#039;&amp;lt;&#039;)&lt;br /&gt;
			.join(&#039;&amp;amp;lt;&#039;)&lt;br /&gt;
			.split(&#039;&amp;gt;&#039;)&lt;br /&gt;
			.join(&#039;&amp;amp;gt;&#039; /*+shy*/)&lt;br /&gt;
			.split(&#039;&amp;quot;&#039;)&lt;br /&gt;
			.join(&#039;&amp;amp;quot;&#039;);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	// Array filter function&lt;br /&gt;
	function removeNulls(val) {&lt;br /&gt;
		return val !== null;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function joinPath(list) {&lt;br /&gt;
		return list.filter(removeNulls).join(&#039;/&#039;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function simplePrintf(str, subs) {&lt;br /&gt;
		if (!str || !subs) {&lt;br /&gt;
			return str;&lt;br /&gt;
		}&lt;br /&gt;
		const ret = [];&lt;br /&gt;
		const s = str.parenSplit(/(%s|\$[0-9]+)/);&lt;br /&gt;
		let i = 0;&lt;br /&gt;
		do {&lt;br /&gt;
			ret.push(s.shift());&lt;br /&gt;
			if (!s.length) {&lt;br /&gt;
				break;&lt;br /&gt;
			}&lt;br /&gt;
			const cmd = s.shift();&lt;br /&gt;
			if (cmd == &#039;%s&#039;) {&lt;br /&gt;
				if (i &amp;lt; subs.length) {&lt;br /&gt;
					ret.push(subs[i]);&lt;br /&gt;
				} else {&lt;br /&gt;
					ret.push(cmd);&lt;br /&gt;
				}&lt;br /&gt;
				++i;&lt;br /&gt;
			} else {&lt;br /&gt;
				const j = parseInt(cmd.replace(&#039;$&#039;, &#039;&#039;), 10) - 1;&lt;br /&gt;
				if (j &amp;gt; -1 &amp;amp;&amp;amp; j &amp;lt; subs.length) {&lt;br /&gt;
					ret.push(subs[j]);&lt;br /&gt;
				} else {&lt;br /&gt;
					ret.push(cmd);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		} while (s.length &amp;gt; 0);&lt;br /&gt;
		return ret.join(&#039;&#039;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* eslint-disable no-unused-vars */&lt;br /&gt;
	function isString(x) {&lt;br /&gt;
		return typeof x === &#039;string&#039; || x instanceof String;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function isNumber(x) {&lt;br /&gt;
		return typeof x === &#039;number&#039; || x instanceof Number;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function isRegExp(x) {&lt;br /&gt;
		return x instanceof RegExp;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function isArray(x) {&lt;br /&gt;
		return x instanceof Array;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function isObject(x) {&lt;br /&gt;
		return x instanceof Object;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function isFunction(x) {&lt;br /&gt;
		return !isRegExp(x) &amp;amp;&amp;amp; (typeof x === &#039;function&#039; || x instanceof Function);&lt;br /&gt;
	}&lt;br /&gt;
	/* eslint-enable no-unused-vars */&lt;br /&gt;
&lt;br /&gt;
	function repeatString(s, mult) {&lt;br /&gt;
		let ret = &#039;&#039;;&lt;br /&gt;
		for (let i = 0; i &amp;lt; mult; ++i) {&lt;br /&gt;
			ret += s;&lt;br /&gt;
		}&lt;br /&gt;
		return ret;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function zeroFill(s, min) {&lt;br /&gt;
		min = min || 2;&lt;br /&gt;
		const t = s.toString();&lt;br /&gt;
		return repeatString(&#039;0&#039;, min - t.length) + t;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function map(f, o) {&lt;br /&gt;
		if (isArray(o)) {&lt;br /&gt;
			return map_array(f, o);&lt;br /&gt;
		}&lt;br /&gt;
		return map_object(f, o);&lt;br /&gt;
	}&lt;br /&gt;
	function map_array(f, o) {&lt;br /&gt;
		const ret = [];&lt;br /&gt;
		for (let i = 0; i &amp;lt; o.length; ++i) {&lt;br /&gt;
			ret.push(f(o[i]));&lt;br /&gt;
		}&lt;br /&gt;
		return ret;&lt;br /&gt;
	}&lt;br /&gt;
	function map_object(f, o) {&lt;br /&gt;
		const ret = {};&lt;br /&gt;
		for (const i in o) {&lt;br /&gt;
			ret[o] = f(o[i]);&lt;br /&gt;
		}&lt;br /&gt;
		return ret;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	pg.escapeQuotesHTML = function (text) {&lt;br /&gt;
		return text&lt;br /&gt;
			.replace(/&amp;amp;/g, &#039;&amp;amp;amp;&#039;)&lt;br /&gt;
			.replace(/&amp;quot;/g, &#039;&amp;amp;quot;&#039;)&lt;br /&gt;
			.replace(/&amp;lt;/g, &#039;&amp;amp;lt;&#039;)&lt;br /&gt;
			.replace(/&amp;gt;/g, &#039;&amp;amp;gt;&#039;);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	pg.unescapeQuotesHTML = function (html) {&lt;br /&gt;
		// From https://stackoverflow.com/a/7394787&lt;br /&gt;
		// This seems to be implemented correctly on all major browsers now, so we&lt;br /&gt;
		// don&#039;t have to make our own function.&lt;br /&gt;
		const txt = document.createElement(&#039;textarea&#039;);&lt;br /&gt;
		txt.innerHTML = html;&lt;br /&gt;
		return txt.value;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	// ENDFILE: tools.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: dab.js&lt;br /&gt;
	//////////////////////////////////////////////////&lt;br /&gt;
	// Dab-fixing code&lt;br /&gt;
	//&lt;br /&gt;
&lt;br /&gt;
	function retargetDab(newTarget, oldTarget, friendlyCurrentArticleName, titleToEdit) {&lt;br /&gt;
		log(&#039;retargetDab: newTarget=&#039; + newTarget + &#039; oldTarget=&#039; + oldTarget);&lt;br /&gt;
		return changeLinkTargetLink({&lt;br /&gt;
			newTarget: newTarget,&lt;br /&gt;
			text: newTarget.split(&#039; &#039;).join(&#039;&amp;amp;nbsp;&#039;),&lt;br /&gt;
			hint: tprintf(&#039;disambigHint&#039;, [newTarget]),&lt;br /&gt;
			summary: simplePrintf(getValueOf(&#039;popupFixDabsSummary&#039;), [&lt;br /&gt;
				friendlyCurrentArticleName,&lt;br /&gt;
				newTarget,&lt;br /&gt;
			]),&lt;br /&gt;
			clickButton: getValueOf(&#039;popupDabsAutoClick&#039;),&lt;br /&gt;
			minor: true,&lt;br /&gt;
			oldTarget: oldTarget,&lt;br /&gt;
			watch: getValueOf(&#039;popupWatchDisambiggedPages&#039;),&lt;br /&gt;
			title: titleToEdit,&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function listLinks(wikitext, oldTarget, titleToEdit) {&lt;br /&gt;
		// mediawiki strips trailing spaces, so we do the same&lt;br /&gt;
		// testcase: https://en.wikipedia.org/w/index.php?title=Radial&amp;amp;oldid=97365633&lt;br /&gt;
		const reg = /\[\[([^|]*?) *(\||\]\])/gi;&lt;br /&gt;
		let ret = [];&lt;br /&gt;
		const splitted = wikitext.parenSplit(reg);&lt;br /&gt;
		// ^[a-z]+ should match interwiki links, hopefully (case-insensitive)&lt;br /&gt;
		// and ^[a-z]* should match those and [[:Category...]] style links too&lt;br /&gt;
		const omitRegex = /^[a-z]*:|^[Ss]pecial:|^[Ii]mage|^[Cc]ategory/;&lt;br /&gt;
		const friendlyCurrentArticleName = oldTarget.toString();&lt;br /&gt;
		const wikPos = getValueOf(&#039;popupDabWiktionary&#039;);&lt;br /&gt;
&lt;br /&gt;
		for (let i = 1; i &amp;lt; splitted.length; i = i + 3) {&lt;br /&gt;
			if (&lt;br /&gt;
				typeof splitted[i] == typeof &#039;string&#039; &amp;amp;&amp;amp;&lt;br /&gt;
				splitted[i].length &amp;gt; 0 &amp;amp;&amp;amp;&lt;br /&gt;
				!omitRegex.test(splitted[i])&lt;br /&gt;
			) {&lt;br /&gt;
				ret.push(retargetDab(splitted[i], oldTarget, friendlyCurrentArticleName, titleToEdit));&lt;br /&gt;
			} /* if */&lt;br /&gt;
		} /* for loop */&lt;br /&gt;
&lt;br /&gt;
		ret = rmDupesFromSortedList(ret.sort());&lt;br /&gt;
&lt;br /&gt;
		if (wikPos) {&lt;br /&gt;
			const wikTarget =&lt;br /&gt;
				&#039;wiktionary:&#039; +&lt;br /&gt;
				friendlyCurrentArticleName.replace(/^(.+)\s+[(][^)]+[)]\s*$/, &#039;$1&#039;);&lt;br /&gt;
&lt;br /&gt;
			let meth;&lt;br /&gt;
			if (wikPos.toLowerCase() == &#039;first&#039;) {&lt;br /&gt;
				meth = &#039;unshift&#039;;&lt;br /&gt;
			} else {&lt;br /&gt;
				meth = &#039;push&#039;;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			ret[meth](retargetDab(wikTarget, oldTarget, friendlyCurrentArticleName, titleToEdit));&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		ret.push(&lt;br /&gt;
			changeLinkTargetLink({&lt;br /&gt;
				newTarget: null,&lt;br /&gt;
				text: popupString(&#039;remove this link&#039;).split(&#039; &#039;).join(&#039;&amp;amp;nbsp;&#039;),&lt;br /&gt;
				hint: popupString(&#039;remove all links to this disambig page from this article&#039;),&lt;br /&gt;
				clickButton: getValueOf(&#039;popupDabsAutoClick&#039;),&lt;br /&gt;
				oldTarget: oldTarget,&lt;br /&gt;
				summary: simplePrintf(getValueOf(&#039;popupRmDabLinkSummary&#039;), [friendlyCurrentArticleName]),&lt;br /&gt;
				watch: getValueOf(&#039;popupWatchDisambiggedPages&#039;),&lt;br /&gt;
				title: titleToEdit,&lt;br /&gt;
			})&lt;br /&gt;
		);&lt;br /&gt;
		return ret;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function rmDupesFromSortedList(list) {&lt;br /&gt;
		const ret = [];&lt;br /&gt;
		for (let i = 0; i &amp;lt; list.length; ++i) {&lt;br /&gt;
			if (ret.length === 0 || list[i] != ret[ret.length - 1]) {&lt;br /&gt;
				ret.push(list[i]);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return ret;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function makeFixDab(data, navpop) {&lt;br /&gt;
		// grab title from parent popup if there is one; default exists in changeLinkTargetLink&lt;br /&gt;
		const titleToEdit = navpop.parentPopup &amp;amp;&amp;amp; navpop.parentPopup.article.toString();&lt;br /&gt;
		const list = listLinks(data, navpop.originalArticle, titleToEdit);&lt;br /&gt;
		if (list.length === 0) {&lt;br /&gt;
			log(&#039;listLinks returned empty list&#039;);&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
		let html = &#039;&amp;lt;hr /&amp;gt;&#039; + popupString(&#039;Click to disambiguate this link to:&#039;) + &#039;&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
		html += list.join(&#039;, &#039;);&lt;br /&gt;
		return html;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function makeFixDabs(wikiText, navpop) {&lt;br /&gt;
		if (&lt;br /&gt;
			getValueOf(&#039;popupFixDabs&#039;) &amp;amp;&amp;amp;&lt;br /&gt;
			isDisambig(wikiText, navpop.article) &amp;amp;&amp;amp;&lt;br /&gt;
			Title.fromURL(location.href).namespaceId() != pg.nsSpecialId &amp;amp;&amp;amp;&lt;br /&gt;
			navpop.article.talkPage()&lt;br /&gt;
		) {&lt;br /&gt;
			setPopupHTML(makeFixDab(wikiText, navpop), &#039;popupFixDab&#039;, navpop.idNumber);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function popupRedlinkHTML(article) {&lt;br /&gt;
		return changeLinkTargetLink({&lt;br /&gt;
			newTarget: null,&lt;br /&gt;
			text: popupString(&#039;remove this link&#039;).split(&#039; &#039;).join(&#039;&amp;amp;nbsp;&#039;),&lt;br /&gt;
			hint: popupString(&#039;remove all links to this page from this article&#039;),&lt;br /&gt;
			clickButton: getValueOf(&#039;popupRedlinkAutoClick&#039;),&lt;br /&gt;
			oldTarget: article.toString(),&lt;br /&gt;
			summary: simplePrintf(getValueOf(&#039;popupRedlinkSummary&#039;), [article.toString()]),&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
	// ENDFILE: dab.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: htmloutput.js&lt;br /&gt;
&lt;br /&gt;
	// this has to use a timer loop as we don&#039;t know if the DOM element exists when we want to set the text&lt;br /&gt;
	function setPopupHTML(str, elementId, popupId, onSuccess, append) {&lt;br /&gt;
		if (typeof popupId === &#039;undefined&#039;) {&lt;br /&gt;
			//console.error(&#039;popupId is not defined in setPopupHTML, html=&#039;+str.substring(0,100));&lt;br /&gt;
			popupId = pg.idNumber;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const popupElement = document.getElementById(elementId + popupId);&lt;br /&gt;
		if (popupElement) {&lt;br /&gt;
			if (!append) {&lt;br /&gt;
				popupElement.innerHTML = &#039;&#039;;&lt;br /&gt;
			}&lt;br /&gt;
			if (isString(str)) {&lt;br /&gt;
				popupElement.innerHTML += str;&lt;br /&gt;
			} else {&lt;br /&gt;
				popupElement.appendChild(str);&lt;br /&gt;
			}&lt;br /&gt;
			if (onSuccess) {&lt;br /&gt;
				onSuccess();&lt;br /&gt;
			}&lt;br /&gt;
			setTimeout(checkPopupPosition, 100);&lt;br /&gt;
			return true;&lt;br /&gt;
		} else {&lt;br /&gt;
			// call this function again in a little while...&lt;br /&gt;
			setTimeout(() =&amp;gt; {&lt;br /&gt;
				setPopupHTML(str, elementId, popupId, onSuccess);&lt;br /&gt;
			}, 600);&lt;br /&gt;
		}&lt;br /&gt;
		return null;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function setPopupTrailer(str, id) {&lt;br /&gt;
		return setPopupHTML(str, &#039;popupData&#039;, id);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// args.navpopup is mandatory&lt;br /&gt;
	// optional: args.redir, args.redirTarget&lt;br /&gt;
	// FIXME: ye gods, this is ugly stuff&lt;br /&gt;
	function fillEmptySpans(args) {&lt;br /&gt;
		// if redir is present and true then redirTarget is mandatory&lt;br /&gt;
		let redir = true;&lt;br /&gt;
		let rcid;&lt;br /&gt;
		if (typeof args != &#039;object&#039; || typeof args.redir == &#039;undefined&#039; || !args.redir) {&lt;br /&gt;
			redir = false;&lt;br /&gt;
		}&lt;br /&gt;
		const a = args.navpopup.parentAnchor;&lt;br /&gt;
&lt;br /&gt;
		let article,&lt;br /&gt;
			hint = null,&lt;br /&gt;
			oldid = null,&lt;br /&gt;
			params = {};&lt;br /&gt;
		if (redir &amp;amp;&amp;amp; typeof args.redirTarget == typeof {}) {&lt;br /&gt;
			article = args.redirTarget;&lt;br /&gt;
			//hint=article.hintValue();&lt;br /&gt;
		} else {&lt;br /&gt;
			article = new Title().fromAnchor(a);&lt;br /&gt;
			hint = a.originalTitle || article.hintValue();&lt;br /&gt;
			params = parseParams(a.href);&lt;br /&gt;
			oldid = getValueOf(&#039;popupHistoricalLinks&#039;) ? params.oldid : null;&lt;br /&gt;
			rcid = params.rcid;&lt;br /&gt;
		}&lt;br /&gt;
		const x = {&lt;br /&gt;
			article: article,&lt;br /&gt;
			hint: hint,&lt;br /&gt;
			oldid: oldid,&lt;br /&gt;
			rcid: rcid,&lt;br /&gt;
			navpop: args.navpopup,&lt;br /&gt;
			params: params,&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		const structure = pg.structures[getValueOf(&#039;popupStructure&#039;)];&lt;br /&gt;
		if (typeof structure != &#039;object&#039;) {&lt;br /&gt;
			setPopupHTML(&lt;br /&gt;
				&#039;popupError&#039;,&lt;br /&gt;
				&#039;Unknown structure (this should never happen): &#039; + pg.option.popupStructure,&lt;br /&gt;
				args.navpopup.idNumber&lt;br /&gt;
			);&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		const spans = flatten(pg.misc.layout);&lt;br /&gt;
		const numspans = spans.length;&lt;br /&gt;
		const redirs = pg.misc.redirSpans;&lt;br /&gt;
&lt;br /&gt;
		for (let i = 0; i &amp;lt; numspans; ++i) {&lt;br /&gt;
			const found = redirs &amp;amp;&amp;amp; redirs.indexOf(spans[i]) !== -1;&lt;br /&gt;
			//log(&#039;redir=&#039;+redir+&#039;, found=&#039;+found+&#039;, spans[i]=&#039;+spans[i]);&lt;br /&gt;
			if ((found &amp;amp;&amp;amp; !redir) || (!found &amp;amp;&amp;amp; redir)) {&lt;br /&gt;
				//log(&#039;skipping this set of the loop&#039;);&lt;br /&gt;
				continue;&lt;br /&gt;
			}&lt;br /&gt;
			const structurefn = structure[spans[i]];&lt;br /&gt;
			if (structurefn === undefined) {&lt;br /&gt;
				// nothing to do for this structure part&lt;br /&gt;
				continue;&lt;br /&gt;
			}&lt;br /&gt;
			let setfn = setPopupHTML;&lt;br /&gt;
			if (&lt;br /&gt;
				getValueOf(&#039;popupActiveNavlinks&#039;) &amp;amp;&amp;amp;&lt;br /&gt;
				(spans[i].indexOf(&#039;popupTopLinks&#039;) === 0 || spans[i].indexOf(&#039;popupRedirTopLinks&#039;) === 0)&lt;br /&gt;
			) {&lt;br /&gt;
				setfn = setPopupTipsAndHTML;&lt;br /&gt;
			}&lt;br /&gt;
			switch (typeof structurefn) {&lt;br /&gt;
				case &#039;function&#039;:&lt;br /&gt;
					log(&lt;br /&gt;
						&#039;running &#039; +&lt;br /&gt;
							spans[i] +&lt;br /&gt;
							&#039;({article:&#039; +&lt;br /&gt;
							x.article +&lt;br /&gt;
							&#039;, hint:&#039; +&lt;br /&gt;
							x.hint +&lt;br /&gt;
							&#039;, oldid: &#039; +&lt;br /&gt;
							x.oldid +&lt;br /&gt;
							&#039;})&#039;&lt;br /&gt;
					);&lt;br /&gt;
					setfn(structurefn(x), spans[i], args.navpopup.idNumber);&lt;br /&gt;
					break;&lt;br /&gt;
				case &#039;string&#039;:&lt;br /&gt;
					setfn(structurefn, spans[i], args.navpopup.idNumber);&lt;br /&gt;
					break;&lt;br /&gt;
				default:&lt;br /&gt;
					errlog(&#039;unknown thing with label &#039; + spans[i] + &#039; (span index was &#039; + i + &#039;)&#039;);&lt;br /&gt;
					break;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// flatten an array&lt;br /&gt;
	function flatten(list, start) {&lt;br /&gt;
		const ret = [];&lt;br /&gt;
		if (typeof start == &#039;undefined&#039;) {&lt;br /&gt;
			start = 0;&lt;br /&gt;
		}&lt;br /&gt;
		for (let i = start; i &amp;lt; list.length; ++i) {&lt;br /&gt;
			if (typeof list[i] == typeof []) {&lt;br /&gt;
				return ret.concat(flatten(list[i])).concat(flatten(list, i + 1));&lt;br /&gt;
			} else {&lt;br /&gt;
				ret.push(list[i]);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return ret;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Generate html for whole popup&lt;br /&gt;
	function popupHTML(a) {&lt;br /&gt;
		getValueOf(&#039;popupStructure&#039;);&lt;br /&gt;
		const structure = pg.structures[pg.option.popupStructure];&lt;br /&gt;
		if (typeof structure != &#039;object&#039;) {&lt;br /&gt;
			//return &#039;Unknown structure: &#039;+pg.option.popupStructure;&lt;br /&gt;
			// override user choice&lt;br /&gt;
			pg.option.popupStructure = pg.optionDefault.popupStructure;&lt;br /&gt;
			return popupHTML(a);&lt;br /&gt;
		}&lt;br /&gt;
		if (typeof structure.popupLayout != &#039;function&#039;) {&lt;br /&gt;
			return &#039;Bad layout&#039;;&lt;br /&gt;
		}&lt;br /&gt;
		pg.misc.layout = structure.popupLayout();&lt;br /&gt;
		if (typeof structure.popupRedirSpans === &#039;function&#039;) {&lt;br /&gt;
			pg.misc.redirSpans = structure.popupRedirSpans();&lt;br /&gt;
		} else {&lt;br /&gt;
			pg.misc.redirSpans = [];&lt;br /&gt;
		}&lt;br /&gt;
		return makeEmptySpans(pg.misc.layout, a.navpopup);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function makeEmptySpans(list, navpop) {&lt;br /&gt;
		let ret = &#039;&#039;;&lt;br /&gt;
		for (let i = 0; i &amp;lt; list.length; ++i) {&lt;br /&gt;
			if (typeof list[i] == typeof &#039;&#039;) {&lt;br /&gt;
				ret += emptySpanHTML(list[i], navpop.idNumber, &#039;div&#039;);&lt;br /&gt;
			} else if (typeof list[i] == typeof [] &amp;amp;&amp;amp; list[i].length &amp;gt; 0) {&lt;br /&gt;
				ret = ret.parenSplit(/(&amp;lt;\/[^&amp;gt;]*?&amp;gt;$)/).join(makeEmptySpans(list[i], navpop));&lt;br /&gt;
			} else if (typeof list[i] == typeof {} &amp;amp;&amp;amp; list[i].nodeType) {&lt;br /&gt;
				ret += emptySpanHTML(list[i].name, navpop.idNumber, list[i].nodeType);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return ret;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function emptySpanHTML(name, id, tag, classname) {&lt;br /&gt;
		tag = tag || &#039;span&#039;;&lt;br /&gt;
		if (!classname) {&lt;br /&gt;
			classname = emptySpanHTML.classAliases[name];&lt;br /&gt;
		}&lt;br /&gt;
		classname = classname || name;&lt;br /&gt;
		if (name == getValueOf(&#039;popupDragHandle&#039;)) {&lt;br /&gt;
			classname += &#039; popupDragHandle&#039;;&lt;br /&gt;
		}&lt;br /&gt;
		return simplePrintf(&#039;&amp;lt;%s id=&amp;quot;%s&amp;quot; class=&amp;quot;%s&amp;quot;&amp;gt;&amp;lt;/%s&amp;gt;&#039;, [tag, name + id, classname, tag]);&lt;br /&gt;
	}&lt;br /&gt;
	emptySpanHTML.classAliases = { popupSecondPreview: &#039;popupPreview&#039; };&lt;br /&gt;
&lt;br /&gt;
	// generate html for popup image&lt;br /&gt;
	// &amp;lt;a id=&amp;quot;popupImageLinkn&amp;quot;&amp;gt;&amp;lt;img id=&amp;quot;popupImagen&amp;quot;&amp;gt;&lt;br /&gt;
	// where n=idNumber&lt;br /&gt;
	function imageHTML(article, idNumber) {&lt;br /&gt;
		return simplePrintf(&lt;br /&gt;
			&#039;&amp;lt;a id=&amp;quot;popupImageLink$1&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
				&#039;&amp;lt;img align=&amp;quot;right&amp;quot; valign=&amp;quot;top&amp;quot; id=&amp;quot;popupImg$1&amp;quot; style=&amp;quot;display: none;&amp;quot;&amp;gt;&amp;lt;/img&amp;gt;&#039; +&lt;br /&gt;
				&#039;&amp;lt;/a&amp;gt;&#039;,&lt;br /&gt;
			[idNumber]&lt;br /&gt;
		);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function popTipsSoonFn(id, when, popData) {&lt;br /&gt;
		if (!when) {&lt;br /&gt;
			when = 250;&lt;br /&gt;
		}&lt;br /&gt;
		const popTips = function () {&lt;br /&gt;
			setupTooltips(document.getElementById(id), false, true, popData);&lt;br /&gt;
		};&lt;br /&gt;
		return function () {&lt;br /&gt;
			setTimeout(popTips, when, popData);&lt;br /&gt;
		};&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function setPopupTipsAndHTML(html, divname, idnumber, popData) {&lt;br /&gt;
		setPopupHTML(&lt;br /&gt;
			html,&lt;br /&gt;
			divname,&lt;br /&gt;
			idnumber,&lt;br /&gt;
			getValueOf(&#039;popupSubpopups&#039;) ? popTipsSoonFn(divname + idnumber, null, popData) : null&lt;br /&gt;
		);&lt;br /&gt;
	}&lt;br /&gt;
	// ENDFILE: htmloutput.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: mouseout.js&lt;br /&gt;
	//////////////////////////////////////////////////&lt;br /&gt;
	// fuzzy checks&lt;br /&gt;
&lt;br /&gt;
	function fuzzyCursorOffMenus(x, y, fuzz, parent) {&lt;br /&gt;
		if (!parent) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
		const uls = parent.getElementsByTagName(&#039;ul&#039;);&lt;br /&gt;
		for (let i = 0; i &amp;lt; uls.length; ++i) {&lt;br /&gt;
			if (uls[i].className == &#039;popup_menu&#039;) {&lt;br /&gt;
				if (uls[i].offsetWidth &amp;gt; 0) {&lt;br /&gt;
					return false;&lt;br /&gt;
				}&lt;br /&gt;
			} // else {document.title+=&#039;.&#039;;}&lt;br /&gt;
		}&lt;br /&gt;
		return true;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function checkPopupPosition() {&lt;br /&gt;
		// stop the popup running off the right of the screen&lt;br /&gt;
		// FIXME avoid pg.current.link&lt;br /&gt;
		if (pg.current.link &amp;amp;&amp;amp; pg.current.link.navpopup) {&lt;br /&gt;
			pg.current.link.navpopup.limitHorizontalPosition();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function mouseOutWikiLink() {&lt;br /&gt;
		//console (&#039;mouseOutWikiLink&#039;);&lt;br /&gt;
		const a = this;&lt;br /&gt;
&lt;br /&gt;
		removeModifierKeyHandler(a);&lt;br /&gt;
&lt;br /&gt;
		if (a.navpopup === null || typeof a.navpopup === &#039;undefined&#039;) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (!a.navpopup.isVisible()) {&lt;br /&gt;
			a.navpopup.banish();&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		restoreTitle(a);&lt;br /&gt;
		Navpopup.tracker.addHook(posCheckerHook(a.navpopup));&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function posCheckerHook(navpop) {&lt;br /&gt;
		return function () {&lt;br /&gt;
			if (!navpop.isVisible()) {&lt;br /&gt;
				return true; /* remove this hook */&lt;br /&gt;
			}&lt;br /&gt;
			if (Navpopup.tracker.dirty) {&lt;br /&gt;
				return false;&lt;br /&gt;
			}&lt;br /&gt;
			const x = Navpopup.tracker.x,&lt;br /&gt;
				y = Navpopup.tracker.y;&lt;br /&gt;
			const mouseOverNavpop =&lt;br /&gt;
				navpop.isWithin(x, y, navpop.fuzz, navpop.mainDiv) ||&lt;br /&gt;
				!fuzzyCursorOffMenus(x, y, navpop.fuzz, navpop.mainDiv);&lt;br /&gt;
&lt;br /&gt;
			// FIXME it&#039;d be prettier to do this internal to the Navpopup objects&lt;br /&gt;
			let t = getValueOf(&#039;popupHideDelay&#039;);&lt;br /&gt;
			if (t) {&lt;br /&gt;
				t = t * 1000;&lt;br /&gt;
			}&lt;br /&gt;
			if (!t) {&lt;br /&gt;
				if (!mouseOverNavpop) {&lt;br /&gt;
					if (navpop.parentAnchor) {&lt;br /&gt;
						restoreTitle(navpop.parentAnchor);&lt;br /&gt;
					}&lt;br /&gt;
					navpop.banish();&lt;br /&gt;
					return true; /* remove this hook */&lt;br /&gt;
				}&lt;br /&gt;
				return false;&lt;br /&gt;
			}&lt;br /&gt;
			// we have a hide delay set&lt;br /&gt;
			const d = Date.now();&lt;br /&gt;
			if (!navpop.mouseLeavingTime) {&lt;br /&gt;
				navpop.mouseLeavingTime = d;&lt;br /&gt;
				return false;&lt;br /&gt;
			}&lt;br /&gt;
			if (mouseOverNavpop) {&lt;br /&gt;
				navpop.mouseLeavingTime = null;&lt;br /&gt;
				return false;&lt;br /&gt;
			}&lt;br /&gt;
			if (d - navpop.mouseLeavingTime &amp;gt; t) {&lt;br /&gt;
				navpop.mouseLeavingTime = null;&lt;br /&gt;
				navpop.banish();&lt;br /&gt;
				return true; /* remove this hook */&lt;br /&gt;
			}&lt;br /&gt;
			return false;&lt;br /&gt;
		};&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function runStopPopupTimer(navpop) {&lt;br /&gt;
		// at this point, we should have left the link but remain within the popup&lt;br /&gt;
		// so we call this function again until we leave the popup.&lt;br /&gt;
		if (!navpop.stopPopupTimer) {&lt;br /&gt;
			navpop.stopPopupTimer = setInterval(posCheckerHook(navpop), 500);&lt;br /&gt;
			navpop.addHook(&lt;br /&gt;
				() =&amp;gt; {&lt;br /&gt;
					clearInterval(navpop.stopPopupTimer);&lt;br /&gt;
				},&lt;br /&gt;
				&#039;hide&#039;,&lt;br /&gt;
				&#039;before&#039;&lt;br /&gt;
			);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	// ENDFILE: mouseout.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: previewmaker.js&lt;br /&gt;
	/**&lt;br /&gt;
	 * @file&lt;br /&gt;
	 * Defines the {@link Previewmaker} object, which generates short previews from wiki markup.&lt;br /&gt;
	 */&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Creates a new Previewmaker&lt;br /&gt;
	 *&lt;br /&gt;
	 * @constructor&lt;br /&gt;
	 * @class The Previewmaker class. Use an instance of this to generate short previews from Wikitext.&lt;br /&gt;
	 * @param {string} wikiText The Wikitext source of the page we wish to preview.&lt;br /&gt;
	 * @param {string} baseUrl The url we should prepend when creating relative urls.&lt;br /&gt;
	 * @param {Navpopup} owner The navpop associated to this preview generator&lt;br /&gt;
	 */&lt;br /&gt;
	function Previewmaker(wikiText, baseUrl, owner) {&lt;br /&gt;
		/** The wikitext which is manipulated to generate the preview. */&lt;br /&gt;
		this.originalData = wikiText;&lt;br /&gt;
		this.baseUrl = baseUrl;&lt;br /&gt;
		this.owner = owner;&lt;br /&gt;
&lt;br /&gt;
		this.maxCharacters = getValueOf(&#039;popupMaxPreviewCharacters&#039;);&lt;br /&gt;
		this.maxSentences = getValueOf(&#039;popupMaxPreviewSentences&#039;);&lt;br /&gt;
&lt;br /&gt;
		this.setData();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	Previewmaker.prototype.setData = function () {&lt;br /&gt;
		const maxSize = Math.max(10000, 2 * this.maxCharacters);&lt;br /&gt;
		this.data = this.originalData.substring(0, maxSize);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Remove HTML comments&lt;br /&gt;
	 *&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.killComments = function () {&lt;br /&gt;
		// this also kills one trailing newline, eg [[diamyo]]&lt;br /&gt;
		this.data = this.data.replace(&lt;br /&gt;
			/^&amp;lt;!--[^$]*?--&amp;gt;\n|\n&amp;lt;!--[^$]*?--&amp;gt;(?=\n)|&amp;lt;!--[^$]*?--&amp;gt;/g,&lt;br /&gt;
			&#039;&#039;&lt;br /&gt;
		);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.killDivs = function () {&lt;br /&gt;
		// say goodbye, divs (can be nested, so use * not *?)&lt;br /&gt;
		this.data = this.data.replace(/&amp;lt; *div[^&amp;gt;]* *&amp;gt;[\s\S]*?&amp;lt; *\/ *div *&amp;gt;/gi, &#039;&#039;);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.killGalleries = function () {&lt;br /&gt;
		this.data = this.data.replace(/&amp;lt; *gallery[^&amp;gt;]* *&amp;gt;[\s\S]*?&amp;lt; *\/ *gallery *&amp;gt;/gi, &#039;&#039;);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.kill = function (opening, closing, subopening, subclosing, repl) {&lt;br /&gt;
		let oldk = this.data;&lt;br /&gt;
		let k = this.killStuff(this.data, opening, closing, subopening, subclosing, repl);&lt;br /&gt;
		while (k.length &amp;lt; oldk.length) {&lt;br /&gt;
			oldk = k;&lt;br /&gt;
			k = this.killStuff(k, opening, closing, subopening, subclosing, repl);&lt;br /&gt;
		}&lt;br /&gt;
		this.data = k;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.killStuff = function (&lt;br /&gt;
		txt,&lt;br /&gt;
		opening,&lt;br /&gt;
		closing,&lt;br /&gt;
		subopening,&lt;br /&gt;
		subclosing,&lt;br /&gt;
		repl&lt;br /&gt;
	) {&lt;br /&gt;
		const op = this.makeRegexp(opening);&lt;br /&gt;
		const cl = this.makeRegexp(closing, &#039;^&#039;);&lt;br /&gt;
		const sb = subopening ? this.makeRegexp(subopening, &#039;^&#039;) : null;&lt;br /&gt;
		const sc = subclosing ? this.makeRegexp(subclosing, &#039;^&#039;) : cl;&lt;br /&gt;
		if (!op || !cl) {&lt;br /&gt;
			alert(&#039;Navigation Popups error: op or cl is null! something is wrong.&#039;);&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (!op.test(txt)) {&lt;br /&gt;
			return txt;&lt;br /&gt;
		}&lt;br /&gt;
		let ret = &#039;&#039;;&lt;br /&gt;
		const opResult = op.exec(txt);&lt;br /&gt;
		ret = txt.substring(0, opResult.index);&lt;br /&gt;
		txt = txt.substring(opResult.index + opResult[0].length);&lt;br /&gt;
		let depth = 1;&lt;br /&gt;
		while (txt.length &amp;gt; 0) {&lt;br /&gt;
			let removal = 0;&lt;br /&gt;
			if (depth == 1 &amp;amp;&amp;amp; cl.test(txt)) {&lt;br /&gt;
				depth--;&lt;br /&gt;
				removal = cl.exec(txt)[0].length;&lt;br /&gt;
			} else if (depth &amp;gt; 1 &amp;amp;&amp;amp; sc.test(txt)) {&lt;br /&gt;
				depth--;&lt;br /&gt;
				removal = sc.exec(txt)[0].length;&lt;br /&gt;
			} else if (sb &amp;amp;&amp;amp; sb.test(txt)) {&lt;br /&gt;
				depth++;&lt;br /&gt;
				removal = sb.exec(txt)[0].length;&lt;br /&gt;
			}&lt;br /&gt;
			if (!removal) {&lt;br /&gt;
				removal = 1;&lt;br /&gt;
			}&lt;br /&gt;
			txt = txt.substring(removal);&lt;br /&gt;
			if (depth === 0) {&lt;br /&gt;
				break;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return ret + (repl || &#039;&#039;) + txt;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.makeRegexp = function (x, prefix, suffix) {&lt;br /&gt;
		prefix = prefix || &#039;&#039;;&lt;br /&gt;
		suffix = suffix || &#039;&#039;;&lt;br /&gt;
		let reStr = &#039;&#039;;&lt;br /&gt;
		let flags = &#039;&#039;;&lt;br /&gt;
		if (isString(x)) {&lt;br /&gt;
			reStr = prefix + literalizeRegex(x) + suffix;&lt;br /&gt;
		} else if (isRegExp(x)) {&lt;br /&gt;
			let s = x.toString().substring(1);&lt;br /&gt;
			const sp = s.split(&#039;/&#039;);&lt;br /&gt;
			flags = sp[sp.length - 1];&lt;br /&gt;
			sp[sp.length - 1] = &#039;&#039;;&lt;br /&gt;
			s = sp.join(&#039;/&#039;);&lt;br /&gt;
			s = s.substring(0, s.length - 1);&lt;br /&gt;
			reStr = prefix + s + suffix;&lt;br /&gt;
		} else {&lt;br /&gt;
			log(&#039;makeRegexp failed&#039;);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		log(&#039;makeRegexp: got reStr=&#039; + reStr + &#039;, flags=&#039; + flags);&lt;br /&gt;
		return RegExp(reStr, flags);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.killBoxTemplates = function () {&lt;br /&gt;
		// taxobox removal... in fact, there&#039;s a saudiprincebox_begin, so let&#039;s be more general&lt;br /&gt;
		// also, have float_begin, ... float_end&lt;br /&gt;
		this.kill(/[{][{][^{}\s|]*?(float|box)[_ ](begin|start)/i, /[}][}]\s*/, &#039;{{&#039;);&lt;br /&gt;
&lt;br /&gt;
		// infoboxes etc&lt;br /&gt;
		// from [[User:Zyxw/popups.js]]: kill frames too&lt;br /&gt;
		this.kill(/[{][{][^{}\s|]*?(infobox|elementbox|frame)[_ ]/i, /[}][}]\s*/, &#039;{{&#039;);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.killTemplates = function () {&lt;br /&gt;
		this.kill(&#039;{{&#039;, &#039;}}&#039;, &#039;{&#039;, &#039;}&#039;, &#039; &#039;);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.killTables = function () {&lt;br /&gt;
		// tables are bad, too&lt;br /&gt;
		// this can be slow, but it&#039;s an inprovement over a browser hang&lt;br /&gt;
		// torture test: [[Comparison_of_Intel_Central_Processing_Units]]&lt;br /&gt;
		this.kill(&#039;{|&#039;, /[|]}\s*/, &#039;{|&#039;);&lt;br /&gt;
		this.kill(/&amp;lt;table.*?&amp;gt;/i, /&amp;lt;\/table.*?&amp;gt;/i, /&amp;lt;table.*?&amp;gt;/i);&lt;br /&gt;
		// remove lines starting with a pipe for the hell of it (?)&lt;br /&gt;
		this.data = this.data.replace(/^[|].*$/mg, &#039;&#039;);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.killImages = function () {&lt;br /&gt;
		const forbiddenNamespaceAliases = [];&lt;br /&gt;
		$.each(mw.config.get(&#039;wgNamespaceIds&#039;), (_localizedNamespaceLc, _namespaceId) =&amp;gt; {&lt;br /&gt;
			if (_namespaceId != pg.nsImageId &amp;amp;&amp;amp; _namespaceId != pg.nsCategoryId) {&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			forbiddenNamespaceAliases.push(_localizedNamespaceLc.split(&#039; &#039;).join(&#039;[ _]&#039;)); //todo: escape regexp fragments!&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		// images and categories are a nono&lt;br /&gt;
		this.kill(&lt;br /&gt;
			RegExp(&#039;[[][[]\\s*(&#039; + forbiddenNamespaceAliases.join(&#039;|&#039;) + &#039;)\\s*:&#039;, &#039;i&#039;),&lt;br /&gt;
			/\]\]\s*/,&lt;br /&gt;
			&#039;[&#039;,&lt;br /&gt;
			&#039;]&#039;&lt;br /&gt;
		);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.killHTML = function () {&lt;br /&gt;
		// kill &amp;lt;ref ...&amp;gt;...&amp;lt;/ref&amp;gt;&lt;br /&gt;
		this.kill(/&amp;lt;ref\b[^/&amp;gt;]*?&amp;gt;/i, /&amp;lt;\/ref&amp;gt;/i);&lt;br /&gt;
&lt;br /&gt;
		// let&#039;s also delete entire lines starting with &amp;lt;. it&#039;s worth a try.&lt;br /&gt;
		this.data = this.data.replace(/(^|\n) *&amp;lt;.*/g, &#039;\n&#039;);&lt;br /&gt;
&lt;br /&gt;
		// and those pesky html tags, but not &amp;lt;nowiki&amp;gt; or &amp;lt;blockquote&amp;gt;&lt;br /&gt;
		const splitted = this.data.parenSplit(/(&amp;lt;[\w\W]*?(?:&amp;gt;|$|(?=&amp;lt;)))/);&lt;br /&gt;
		const len = splitted.length;&lt;br /&gt;
		for (let i = 1; i &amp;lt; len; i = i + 2) {&lt;br /&gt;
			switch (splitted[i]) {&lt;br /&gt;
				case &#039;&amp;lt;nowiki&amp;gt;&#039;:&lt;br /&gt;
				case &#039;&amp;lt;/nowiki&amp;gt;&#039;:&lt;br /&gt;
				case &#039;&amp;lt;blockquote&amp;gt;&#039;:&lt;br /&gt;
				case &#039;&amp;lt;/blockquote&amp;gt;&#039;:&lt;br /&gt;
					break;&lt;br /&gt;
				default:&lt;br /&gt;
					splitted[i] = &#039;&#039;;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		this.data = splitted.join(&#039;&#039;);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.killChunks = function () {&lt;br /&gt;
		// heuristics alert&lt;br /&gt;
		// chunks of italic text? you crazy, man?&lt;br /&gt;
		const italicChunkRegex = /((^|\n)\s*:*\s*&#039;&#039;[^&#039;]([^&#039;]|&#039;&#039;&#039;|&#039;[^&#039;]){20}(.|\n[^\n])*&#039;&#039;[.!?\s]*\n)+/g;&lt;br /&gt;
		// keep stuff separated, though, so stick in \n (fixes [[Union Jack]]?&lt;br /&gt;
		this.data = this.data.replace(italicChunkRegex, &#039;\n&#039;);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.mopup = function () {&lt;br /&gt;
		// we simply *can&#039;t* be doing with horizontal rules right now&lt;br /&gt;
		this.data = this.data.replace(/^-{4,}/mg, &#039;&#039;);&lt;br /&gt;
&lt;br /&gt;
		// no indented lines&lt;br /&gt;
		this.data = this.data.replace(/(^|\n) *:[^\n]*/g, &#039;&#039;);&lt;br /&gt;
&lt;br /&gt;
		// replace __TOC__, __NOTOC__ and whatever else there is&lt;br /&gt;
		// this&#039;ll probably do&lt;br /&gt;
		this.data = this.data.replace(/^__[A-Z_]*__ *$/gmi, &#039;&#039;);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.firstBit = function () {&lt;br /&gt;
		// dont&#039;t be givin&#039; me no subsequent paragraphs, you hear me?&lt;br /&gt;
		/// first we &amp;quot;normalize&amp;quot; section headings, removing whitespace after, adding before&lt;br /&gt;
		let d = this.data;&lt;br /&gt;
&lt;br /&gt;
		if (getValueOf(&#039;popupPreviewCutHeadings&#039;)) {&lt;br /&gt;
			this.data = this.data.replace(/\s*(==+[^=]*==+)\s*/g, &#039;\n\n$1 &#039;);&lt;br /&gt;
			/// then we want to get rid of paragraph breaks whose text ends badly&lt;br /&gt;
			this.data = this.data.replace(/([:;]) *\n{2,}/g, &#039;$1\n&#039;);&lt;br /&gt;
&lt;br /&gt;
			this.data = this.data.replace(/^[\s\n]*/, &#039;&#039;);&lt;br /&gt;
			const stuff = /^([^\n]|\n[^\n\s])*/.exec(this.data);&lt;br /&gt;
			if (stuff) {&lt;br /&gt;
				d = stuff[0];&lt;br /&gt;
			}&lt;br /&gt;
			if (!getValueOf(&#039;popupPreviewFirstParOnly&#039;)) {&lt;br /&gt;
				d = this.data;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			/// now put \n\n after sections so that bullets and numbered lists work&lt;br /&gt;
			d = d.replace(/(==+[^=]*==+)\s*/g, &#039;$1\n\n&#039;);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Split sentences. Superfluous sentences are RIGHT OUT.&lt;br /&gt;
		// note: exactly 1 set of parens here needed to make the slice work&lt;br /&gt;
		d = d.parenSplit(/([!?.]+[&amp;quot;&#039;]*\s)/g);&lt;br /&gt;
		// leading space is bad, mmkay?&lt;br /&gt;
		d[0] = d[0].replace(/^\s*/, &#039;&#039;);&lt;br /&gt;
&lt;br /&gt;
		const notSentenceEnds = /([^.][a-z][.] *[a-z]|etc|sic|Dr|Mr|Mrs|Ms|St|no|op|cit|\[[^\]]*|\s[A-Zvclm])$/i;&lt;br /&gt;
		d = this.fixSentenceEnds(d, notSentenceEnds);&lt;br /&gt;
&lt;br /&gt;
		this.fullLength = d.join(&#039;&#039;).length;&lt;br /&gt;
		let n = this.maxSentences;&lt;br /&gt;
		let dd = this.firstSentences(d, n);&lt;br /&gt;
&lt;br /&gt;
		do {&lt;br /&gt;
			dd = this.firstSentences(d, n);&lt;br /&gt;
			--n;&lt;br /&gt;
		} while (dd.length &amp;gt; this.maxCharacters &amp;amp;&amp;amp; n !== 0);&lt;br /&gt;
&lt;br /&gt;
		this.data = dd;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.fixSentenceEnds = function (strs, reg) {&lt;br /&gt;
		// take an array of strings, strs&lt;br /&gt;
		// join strs[i] to strs[i+1] &amp;amp; strs[i+2] if strs[i] matches regex reg&lt;br /&gt;
&lt;br /&gt;
		for (let i = 0; i &amp;lt; strs.length - 2; ++i) {&lt;br /&gt;
			if (reg.test(strs[i])) {&lt;br /&gt;
				const a = [];&lt;br /&gt;
				for (let j = 0; j &amp;lt; strs.length; ++j) {&lt;br /&gt;
					if (j &amp;lt; i) {&lt;br /&gt;
						a[j] = strs[j];&lt;br /&gt;
					}&lt;br /&gt;
					if (j == i) {&lt;br /&gt;
						a[i] = strs[i] + strs[i + 1] + strs[i + 2];&lt;br /&gt;
					}&lt;br /&gt;
					if (j &amp;gt; i + 2) {&lt;br /&gt;
						a[j - 2] = strs[j];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				return this.fixSentenceEnds(a, reg);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return strs;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.firstSentences = function (strs, howmany) {&lt;br /&gt;
		const t = strs.slice(0, 2 * howmany);&lt;br /&gt;
		return t.join(&#039;&#039;);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.killBadWhitespace = function () {&lt;br /&gt;
		// also cleans up isolated &#039;&#039;&#039;&#039;, eg [[Suntory Sungoliath]]&lt;br /&gt;
		this.data = this.data.replace(/^ *&#039;+ *$/gm, &#039;&#039;);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Runs the various methods to generate the preview.&lt;br /&gt;
	 * The preview is stored in the &amp;lt;code&amp;gt;html&amp;lt;/html&amp;gt; field.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.makePreview = function () {&lt;br /&gt;
		if (&lt;br /&gt;
			this.owner.article.namespaceId() != pg.nsTemplateId &amp;amp;&amp;amp;&lt;br /&gt;
			this.owner.article.namespaceId() != pg.nsImageId&lt;br /&gt;
		) {&lt;br /&gt;
			this.killComments();&lt;br /&gt;
			this.killDivs();&lt;br /&gt;
			this.killGalleries();&lt;br /&gt;
			this.killBoxTemplates();&lt;br /&gt;
&lt;br /&gt;
			if (getValueOf(&#039;popupPreviewKillTemplates&#039;)) {&lt;br /&gt;
				this.killTemplates();&lt;br /&gt;
			} else {&lt;br /&gt;
				this.killMultilineTemplates();&lt;br /&gt;
			}&lt;br /&gt;
			this.killTables();&lt;br /&gt;
			this.killImages();&lt;br /&gt;
			this.killHTML();&lt;br /&gt;
			this.killChunks();&lt;br /&gt;
			this.mopup();&lt;br /&gt;
&lt;br /&gt;
			this.firstBit();&lt;br /&gt;
			this.killBadWhitespace();&lt;br /&gt;
		} else {&lt;br /&gt;
			this.killHTML();&lt;br /&gt;
		}&lt;br /&gt;
		this.html = wiki2html(this.data, this.baseUrl); // needs livepreview&lt;br /&gt;
		this.fixHTML();&lt;br /&gt;
		this.stripLongTemplates();&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.esWiki2HtmlPart = function (data) {&lt;br /&gt;
		const reLinks = /(?:\[\[([^|\]]*)(?:\|([^|\]]*))*]]([a-z]*))/gi; //match a wikilink&lt;br /&gt;
		reLinks.lastIndex = 0; //reset regex&lt;br /&gt;
&lt;br /&gt;
		let match;&lt;br /&gt;
		let result = &#039;&#039;;&lt;br /&gt;
		let postfixIndex = 0;&lt;br /&gt;
		while ((match = reLinks.exec(data))) {&lt;br /&gt;
			//match all wikilinks&lt;br /&gt;
			//FIXME: the way that link is built here isn&#039;t perfect. It is clickable, but popups preview won&#039;t recognize it in some cases.&lt;br /&gt;
			result +=&lt;br /&gt;
				pg.escapeQuotesHTML(data.substring(postfixIndex, match.index)) +&lt;br /&gt;
				&#039;&amp;lt;a href=&amp;quot;&#039; +&lt;br /&gt;
				Insta.conf.paths.articles +&lt;br /&gt;
				pg.escapeQuotesHTML(match[1]) +&lt;br /&gt;
				&#039;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
				pg.escapeQuotesHTML((match[2] ? match[2] : match[1]) + match[3]) +&lt;br /&gt;
				&#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
			postfixIndex = reLinks.lastIndex;&lt;br /&gt;
		}&lt;br /&gt;
		//append the rest&lt;br /&gt;
		result += pg.escapeQuotesHTML(data.substring(postfixIndex));&lt;br /&gt;
&lt;br /&gt;
		return result;&lt;br /&gt;
	};&lt;br /&gt;
	Previewmaker.prototype.editSummaryPreview = function () {&lt;br /&gt;
		const reAes = /\/\* *(.*?) *\*\//g; //match the first section marker&lt;br /&gt;
		reAes.lastIndex = 0; //reset regex&lt;br /&gt;
&lt;br /&gt;
		let match;&lt;br /&gt;
&lt;br /&gt;
		match = reAes.exec(this.data);&lt;br /&gt;
		if (match) {&lt;br /&gt;
			//we have a section link. Split it, process it, combine it.&lt;br /&gt;
			const prefix = this.data.substring(0, match.index - 1);&lt;br /&gt;
			const section = match[1];&lt;br /&gt;
			const postfix = this.data.substring(reAes.lastIndex);&lt;br /&gt;
&lt;br /&gt;
			let start = &amp;quot;&amp;lt;span class=&#039;autocomment&#039;&amp;gt;&amp;quot;;&lt;br /&gt;
			let end = &#039;&amp;lt;/span&amp;gt;&#039;;&lt;br /&gt;
			if (prefix.length &amp;gt; 0) {&lt;br /&gt;
				start = this.esWiki2HtmlPart(prefix) + &#039; &#039; + start + &#039;- &#039;;&lt;br /&gt;
			}&lt;br /&gt;
			if (postfix.length &amp;gt; 0) {&lt;br /&gt;
				end = &#039;: &#039; + end + this.esWiki2HtmlPart(postfix);&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			const t = new Title().fromURL(this.baseUrl);&lt;br /&gt;
			t.anchorFromUtf(section);&lt;br /&gt;
			const sectionLink =&lt;br /&gt;
				Insta.conf.paths.articles +&lt;br /&gt;
				pg.escapeQuotesHTML(t.toString(true)) +&lt;br /&gt;
				&#039;#&#039; +&lt;br /&gt;
				pg.escapeQuotesHTML(t.anchor);&lt;br /&gt;
			return (&lt;br /&gt;
				start + &#039;&amp;lt;a href=&amp;quot;&#039; + sectionLink + &#039;&amp;quot;&amp;gt;&amp;amp;rarr;&amp;lt;/a&amp;gt; &#039; + pg.escapeQuotesHTML(section) + end&lt;br /&gt;
			);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		//else there&#039;s no section link, htmlify the whole thing.&lt;br /&gt;
		return this.esWiki2HtmlPart(this.data);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/** Test function for debugging preview problems one step at a time. */&lt;br /&gt;
	/*eslint-disable */&lt;br /&gt;
	function previewSteps(txt) {&lt;br /&gt;
		try {&lt;br /&gt;
			txt = txt || document.editform.wpTextbox1.value;&lt;br /&gt;
		} catch (err) {&lt;br /&gt;
			if (pg.cache.pages.length &amp;gt; 0) {&lt;br /&gt;
				txt = pg.cache.pages[pg.cache.pages.length - 1].data;&lt;br /&gt;
			} else {&lt;br /&gt;
				alert(&#039;provide text or use an edit page&#039;);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		txt = txt.substring(0, 10000);&lt;br /&gt;
		var base = pg.wiki.articlebase + Title.fromURL(document.location.href).urlString();&lt;br /&gt;
		var p = new Previewmaker(txt, base, pg.current.link.navpopup);&lt;br /&gt;
		if (this.owner.article.namespaceId() != pg.nsTemplateId) {&lt;br /&gt;
			p.killComments();&lt;br /&gt;
			if (!confirm(&#039;done killComments(). Continue?\n---\n&#039; + p.data)) {&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			p.killDivs();&lt;br /&gt;
			if (!confirm(&#039;done killDivs(). Continue?\n---\n&#039; + p.data)) {&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			p.killGalleries();&lt;br /&gt;
			if (!confirm(&#039;done killGalleries(). Continue?\n---\n&#039; + p.data)) {&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			p.killBoxTemplates();&lt;br /&gt;
			if (!confirm(&#039;done killBoxTemplates(). Continue?\n---\n&#039; + p.data)) {&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			if (getValueOf(&#039;popupPreviewKillTemplates&#039;)) {&lt;br /&gt;
				p.killTemplates();&lt;br /&gt;
				if (!confirm(&#039;done killTemplates(). Continue?\n---\n&#039; + p.data)) {&lt;br /&gt;
					return;&lt;br /&gt;
				}&lt;br /&gt;
			} else {&lt;br /&gt;
				p.killMultilineTemplates();&lt;br /&gt;
				if (!confirm(&#039;done killMultilineTemplates(). Continue?\n---\n&#039; + p.data)) {&lt;br /&gt;
					return;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			p.killTables();&lt;br /&gt;
			if (!confirm(&#039;done killTables(). Continue?\n---\n&#039; + p.data)) {&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			p.killImages();&lt;br /&gt;
			if (!confirm(&#039;done killImages(). Continue?\n---\n&#039; + p.data)) {&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			p.killHTML();&lt;br /&gt;
			if (!confirm(&#039;done killHTML(). Continue?\n---\n&#039; + p.data)) {&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			p.killChunks();&lt;br /&gt;
			if (!confirm(&#039;done killChunks(). Continue?\n---\n&#039; + p.data)) {&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			p.mopup();&lt;br /&gt;
			if (!confirm(&#039;done mopup(). Continue?\n---\n&#039; + p.data)) {&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			p.firstBit();&lt;br /&gt;
			if (!confirm(&#039;done firstBit(). Continue?\n---\n&#039; + p.data)) {&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			p.killBadWhitespace();&lt;br /&gt;
			if (!confirm(&#039;done killBadWhitespace(). Continue?\n---\n&#039; + p.data)) {&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		p.html = wiki2html(p.data, base); // needs livepreview&lt;br /&gt;
		p.fixHTML();&lt;br /&gt;
		if (!confirm(&#039;done fixHTML(). Continue?\n---\n&#039; + p.html)) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		p.stripLongTemplates();&lt;br /&gt;
		if (!confirm(&#039;done stripLongTemplates(). Continue?\n---\n&#039; + p.html)) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		alert(&#039;finished preview - end result follows.\n---\n&#039; + p.html);&lt;br /&gt;
	}&lt;br /&gt;
	/*eslint-enable */&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Works around livepreview bugs.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.fixHTML = function () {&lt;br /&gt;
		if (!this.html) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		let ret = this.html;&lt;br /&gt;
&lt;br /&gt;
		// fix question marks in wiki links&lt;br /&gt;
		// maybe this&#039;ll break some stuff :-(&lt;br /&gt;
		ret = ret.replace(&lt;br /&gt;
			RegExp(&#039;(&amp;lt;a href=&amp;quot;&#039; + pg.wiki.articlePath + &#039;/[^&amp;quot;]*)[?](.*?&amp;quot;)&#039;, &#039;g&#039;),&lt;br /&gt;
			&#039;$1%3F$2&#039;&lt;br /&gt;
		);&lt;br /&gt;
		ret = ret.replace(&lt;br /&gt;
			RegExp(&amp;quot;(&amp;lt;a href=&#039;&amp;quot; + pg.wiki.articlePath + &amp;quot;/[^&#039;]*)[?](.*?&#039;)&amp;quot;, &#039;g&#039;),&lt;br /&gt;
			&#039;$1%3F$2&#039;&lt;br /&gt;
		);&lt;br /&gt;
		// FIXME fix up % too&lt;br /&gt;
&lt;br /&gt;
		this.html = ret;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Generates the preview and displays it in the current popup.&lt;br /&gt;
	 *&lt;br /&gt;
	 * Does nothing if the generated preview is invalid or consists of whitespace only.&lt;br /&gt;
	 * Also activates wikilinks in the preview for subpopups if the popupSubpopups option is true.&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.showPreview = function () {&lt;br /&gt;
		this.makePreview();&lt;br /&gt;
		if (typeof this.html != typeof &#039;&#039;) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (/^\s*$/.test(this.html)) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		setPopupHTML(&#039;&amp;lt;hr /&amp;gt;&#039;, &#039;popupPrePreviewSep&#039;, this.owner.idNumber);&lt;br /&gt;
		setPopupTipsAndHTML(this.html, &#039;popupPreview&#039;, this.owner.idNumber, {&lt;br /&gt;
			owner: this.owner,&lt;br /&gt;
		});&lt;br /&gt;
		const more = this.fullLength &amp;gt; this.data.length ? this.moreLink() : &#039;&#039;;&lt;br /&gt;
		setPopupHTML(more, &#039;popupPreviewMore&#039;, this.owner.idNumber);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.moreLink = function () {&lt;br /&gt;
		const a = document.createElement(&#039;a&#039;);&lt;br /&gt;
		a.className = &#039;popupMoreLink&#039;;&lt;br /&gt;
		a.innerHTML = popupString(&#039;more...&#039;);&lt;br /&gt;
		const savedThis = this;&lt;br /&gt;
		a.onclick = function () {&lt;br /&gt;
			savedThis.maxCharacters += 2000;&lt;br /&gt;
			savedThis.maxSentences += 20;&lt;br /&gt;
			savedThis.setData();&lt;br /&gt;
			savedThis.showPreview();&lt;br /&gt;
		};&lt;br /&gt;
		return a;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.stripLongTemplates = function () {&lt;br /&gt;
		// operates on the HTML!&lt;br /&gt;
		this.html = this.html.replace(&lt;br /&gt;
			/^.{0,1000}[{][{][^}]*?(&amp;lt;(p|br)( \/)?&amp;gt;\s*){2,}([^{}]*?[}][}])?/gi,&lt;br /&gt;
			&#039;&#039;&lt;br /&gt;
		);&lt;br /&gt;
		this.html = this.html.split(&#039;\n&#039;).join(&#039; &#039;); // workaround for &amp;lt;pre&amp;gt; templates&lt;br /&gt;
		this.html = this.html.replace(/[{][{][^}]*&amp;lt;pre&amp;gt;[^}]*[}][}]/gi, &#039;&#039;);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Previewmaker.prototype.killMultilineTemplates = function () {&lt;br /&gt;
		this.kill(&#039;{{{&#039;, &#039;}}}&#039;);&lt;br /&gt;
		this.kill(/\s*[{][{][^{}]*\n/, &#039;}}&#039;, &#039;{{&#039;);&lt;br /&gt;
	};&lt;br /&gt;
	// ENDFILE: previewmaker.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: querypreview.js&lt;br /&gt;
	function loadAPIPreview(queryType, article, navpop) {&lt;br /&gt;
		const art = new Title(article).urlString();&lt;br /&gt;
		let url = pg.wiki.apiwikibase + &#039;?format=json&amp;amp;formatversion=2&amp;amp;action=query&amp;amp;&#039;;&lt;br /&gt;
		let htmlGenerator = function (/*a, d*/) {&lt;br /&gt;
			alert(&#039;invalid html generator&#039;);&lt;br /&gt;
		};&lt;br /&gt;
		let usernameart = &#039;&#039;;&lt;br /&gt;
		switch (queryType) {&lt;br /&gt;
			case &#039;history&#039;:&lt;br /&gt;
				url +=&lt;br /&gt;
					&#039;titles=&#039; + art + &#039;&amp;amp;prop=revisions&amp;amp;rvlimit=&#039; + getValueOf(&#039;popupHistoryPreviewLimit&#039;);&lt;br /&gt;
				htmlGenerator = APIhistoryPreviewHTML;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;category&#039;:&lt;br /&gt;
				url += &#039;list=categorymembers&amp;amp;cmtitle=&#039; + art;&lt;br /&gt;
				htmlGenerator = APIcategoryPreviewHTML;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;userinfo&#039;:&lt;br /&gt;
				var username = new Title(article).userName();&lt;br /&gt;
				usernameart = encodeURIComponent(username);&lt;br /&gt;
				if (pg.re.ipUser.test(username)) {&lt;br /&gt;
					url += &#039;list=blocks&amp;amp;bkprop=range|restrictions&amp;amp;bkip=&#039; + usernameart;&lt;br /&gt;
				} else {&lt;br /&gt;
					url +=&lt;br /&gt;
						&#039;list=users|usercontribs&amp;amp;usprop=blockinfo|groups|editcount|registration|gender&amp;amp;ususers=&#039; +&lt;br /&gt;
						usernameart +&lt;br /&gt;
						&#039;&amp;amp;meta=globaluserinfo&amp;amp;guiprop=groups|unattached&amp;amp;guiuser=&#039; +&lt;br /&gt;
						usernameart +&lt;br /&gt;
						&#039;&amp;amp;uclimit=1&amp;amp;ucprop=timestamp&amp;amp;ucuser=&#039; +&lt;br /&gt;
						usernameart;&lt;br /&gt;
				}&lt;br /&gt;
				htmlGenerator = APIuserInfoPreviewHTML;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;contribs&#039;:&lt;br /&gt;
				usernameart = encodeURIComponent(new Title(article).userName());&lt;br /&gt;
				url +=&lt;br /&gt;
					&#039;list=usercontribs&amp;amp;ucuser=&#039; +&lt;br /&gt;
					usernameart +&lt;br /&gt;
					&#039;&amp;amp;uclimit=&#039; +&lt;br /&gt;
					getValueOf(&#039;popupContribsPreviewLimit&#039;);&lt;br /&gt;
				htmlGenerator = APIcontribsPreviewHTML;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;imagepagepreview&#039;:&lt;br /&gt;
				var trail = &#039;&#039;;&lt;br /&gt;
				if (getValueOf(&#039;popupImageLinks&#039;)) {&lt;br /&gt;
					trail = &#039;&amp;amp;list=imageusage&amp;amp;iutitle=&#039; + art;&lt;br /&gt;
				}&lt;br /&gt;
				url += &#039;titles=&#039; + art + &#039;&amp;amp;prop=revisions|imageinfo&amp;amp;rvslots=main&amp;amp;rvprop=content&#039; + trail;&lt;br /&gt;
				htmlGenerator = APIimagepagePreviewHTML;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;backlinks&#039;:&lt;br /&gt;
				url += &#039;list=backlinks&amp;amp;bltitle=&#039; + art;&lt;br /&gt;
				htmlGenerator = APIbacklinksPreviewHTML;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;revision&#039;:&lt;br /&gt;
				if (article.oldid) {&lt;br /&gt;
					url += &#039;revids=&#039; + article.oldid;&lt;br /&gt;
				} else {&lt;br /&gt;
					url += &#039;titles=&#039; + article.removeAnchor().urlString();&lt;br /&gt;
				}&lt;br /&gt;
				url +=&lt;br /&gt;
					&#039;&amp;amp;prop=revisions|pageprops|info|images|categories&amp;amp;meta=wikibase&amp;amp;rvslots=main&amp;amp;rvprop=ids|timestamp|flags|comment|user|content&amp;amp;cllimit=max&amp;amp;imlimit=max&#039;;&lt;br /&gt;
				htmlGenerator = APIrevisionPreviewHTML;&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
		pendingNavpopTask(navpop);&lt;br /&gt;
		const callback = function (d) {&lt;br /&gt;
			log(&#039;callback of API functions was hit&#039;);&lt;br /&gt;
			if (queryType === &#039;userinfo&#039;) {&lt;br /&gt;
				// We need to do another API request&lt;br /&gt;
				fetchUserGroupNames(d.data).then(() =&amp;gt; {&lt;br /&gt;
					showAPIPreview(queryType, htmlGenerator(article, d, navpop), navpop.idNumber, navpop, d);&lt;br /&gt;
				});&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			showAPIPreview(queryType, htmlGenerator(article, d, navpop), navpop.idNumber, navpop, d);&lt;br /&gt;
		};&lt;br /&gt;
		const go = function () {&lt;br /&gt;
			getPageWithCaching(url, callback, navpop);&lt;br /&gt;
			return true;&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		if (navpop.visible || !getValueOf(&#039;popupLazyDownloads&#039;)) {&lt;br /&gt;
			go();&lt;br /&gt;
		} else {&lt;br /&gt;
			navpop.addHook(go, &#039;unhide&#039;, &#039;before&#039;, &#039;DOWNLOAD_&#039; + queryType + &#039;_QUERY_DATA&#039;);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function linkList(list) {&lt;br /&gt;
		list.sort((x, y) =&amp;gt; x == y ? 0 : x &amp;lt; y ? -1 : 1);&lt;br /&gt;
		const buf = [];&lt;br /&gt;
		for (let i = 0; i &amp;lt; list.length; ++i) {&lt;br /&gt;
			buf.push(&lt;br /&gt;
				wikiLink({&lt;br /&gt;
					article: new Title(list[i]),&lt;br /&gt;
					text: list[i].split(&#039; &#039;).join(&#039;&amp;amp;nbsp;&#039;),&lt;br /&gt;
					action: &#039;view&#039;,&lt;br /&gt;
				})&lt;br /&gt;
			);&lt;br /&gt;
		}&lt;br /&gt;
		return buf.join(&#039;, &#039;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function getTimeOffset() {&lt;br /&gt;
		const tz = mw.user.options.get(&#039;timecorrection&#039;);&lt;br /&gt;
&lt;br /&gt;
		if (tz) {&lt;br /&gt;
			if (tz.indexOf(&#039;|&#039;) &amp;gt; -1) {&lt;br /&gt;
				// New format&lt;br /&gt;
				return parseInt(tz.split(&#039;|&#039;)[1], 10);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function getTimeZone() {&lt;br /&gt;
		if (!pg.user.timeZone) {&lt;br /&gt;
			const tz = mw.user.options.get(&#039;timecorrection&#039;);&lt;br /&gt;
			pg.user.timeZone = &#039;UTC&#039;;&lt;br /&gt;
&lt;br /&gt;
			if (tz) {&lt;br /&gt;
				const tzComponents = tz.split(&#039;|&#039;);&lt;br /&gt;
				if (tzComponents.length === 3 &amp;amp;&amp;amp; tzComponents[0] === &#039;ZoneInfo&#039;) {&lt;br /&gt;
					pg.user.timeZone = tzComponents[2];&lt;br /&gt;
				} else {&lt;br /&gt;
					errlog(&#039;Unexpected timezone information: &#039; + tz);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return pg.user.timeZone;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Should we use an offset or can we use proper timezones&lt;br /&gt;
	 */&lt;br /&gt;
	function useTimeOffset() {&lt;br /&gt;
		if (typeof Intl.DateTimeFormat.prototype.formatToParts === &#039;undefined&#039;) {&lt;br /&gt;
			// IE 11&lt;br /&gt;
			return true;&lt;br /&gt;
		}&lt;br /&gt;
		const tz = mw.user.options.get(&#039;timecorrection&#039;);&lt;br /&gt;
		if (tz &amp;amp;&amp;amp; tz.indexOf(&#039;ZoneInfo|&#039;) === -1) {&lt;br /&gt;
			// System| Default system time, default for users who didn&#039;t configure timezone&lt;br /&gt;
			// Offset| Manual defined offset by user&lt;br /&gt;
			return true;&lt;br /&gt;
		}&lt;br /&gt;
		return false;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of locales for the purpose of javascript locale based formatting&lt;br /&gt;
	 * Filters down to those supported by the browser. Empty [] === System&#039;s default locale&lt;br /&gt;
	 */&lt;br /&gt;
	function getLocales() {&lt;br /&gt;
		if (!pg.user.locales) {&lt;br /&gt;
			let userLanguage = document.querySelector(&#039;html&#039;).getAttribute(&#039;lang&#039;); // make sure we have HTML locale&lt;br /&gt;
			if (getValueOf(&#039;popupLocale&#039;)) {&lt;br /&gt;
				userLanguage = getValueOf(&#039;popupLocale&#039;);&lt;br /&gt;
			} else if (userLanguage === &#039;en&#039;) {&lt;br /&gt;
				// en.wp tends to treat this as international english / unspecified&lt;br /&gt;
				// but we have more specific settings in user options&lt;br /&gt;
				if (getMWDateFormat() === &#039;mdy&#039;) {&lt;br /&gt;
					userLanguage = &#039;en-US&#039;;&lt;br /&gt;
				} else {&lt;br /&gt;
					userLanguage = &#039;en-GB&#039;;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			pg.user.locales = Intl.DateTimeFormat.supportedLocalesOf([userLanguage, navigator.language]);&lt;br /&gt;
		}&lt;br /&gt;
		return pg.user.locales;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Retrieve configured MW date format for this user&lt;br /&gt;
	 * These can be&lt;br /&gt;
	 * default&lt;br /&gt;
	 * dmy: time, dmy&lt;br /&gt;
	 * mdy: time, mdy&lt;br /&gt;
	 * ymd: time, ymd&lt;br /&gt;
	 * dmyt: dmy, time&lt;br /&gt;
	 * dmyts: dmy, time + seconds&lt;br /&gt;
	 * ISO 8601: YYYY-MM-DDThh:mm:ss (local time)&lt;br /&gt;
	 *&lt;br /&gt;
	 * This isn&#039;t too useful for us, as JS doesn&#039;t have formatters to match these private specifiers&lt;br /&gt;
	 */&lt;br /&gt;
	function getMWDateFormat() {&lt;br /&gt;
		return mw.user.options.get(&#039;date&#039;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Creates a HTML table that&#039;s shown in the history and user-contribs popups.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param {Object[]} h - a list of revisions, returned from the API&lt;br /&gt;
	 * @param {boolean} reallyContribs - true only if we&#039;re displaying user contributions&lt;br /&gt;
	 */&lt;br /&gt;
	function editPreviewTable(article, h, reallyContribs) {&lt;br /&gt;
		let html = [&#039;&amp;lt;table&amp;gt;&#039;];&lt;br /&gt;
		let day = null;&lt;br /&gt;
		let curart = article;&lt;br /&gt;
		let page = null;&lt;br /&gt;
&lt;br /&gt;
		let makeFirstColumnLinks;&lt;br /&gt;
		if (reallyContribs) {&lt;br /&gt;
			// We&#039;re showing user contributions, so make (diff | hist) links&lt;br /&gt;
			makeFirstColumnLinks = function (currentRevision) {&lt;br /&gt;
				let result = &#039;(&#039;;&lt;br /&gt;
				result +=&lt;br /&gt;
					&#039;&amp;lt;a href=&amp;quot;&#039; +&lt;br /&gt;
					pg.wiki.titlebase +&lt;br /&gt;
					new Title(currentRevision.title).urlString() +&lt;br /&gt;
					&#039;&amp;amp;diff=prev&#039; +&lt;br /&gt;
					&#039;&amp;amp;oldid=&#039; +&lt;br /&gt;
					currentRevision.revid +&lt;br /&gt;
					&#039;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
					popupString(&#039;diff&#039;) +&lt;br /&gt;
					&#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
				result += &#039;&amp;amp;nbsp;|&amp;amp;nbsp;&#039;;&lt;br /&gt;
				result +=&lt;br /&gt;
					&#039;&amp;lt;a href=&amp;quot;&#039; +&lt;br /&gt;
					pg.wiki.titlebase +&lt;br /&gt;
					new Title(currentRevision.title).urlString() +&lt;br /&gt;
					&#039;&amp;amp;action=history&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
					popupString(&#039;hist&#039;) +&lt;br /&gt;
					&#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
				result += &#039;)&#039;;&lt;br /&gt;
				return result;&lt;br /&gt;
			};&lt;br /&gt;
		} else {&lt;br /&gt;
			// It&#039;s a regular history page, so make (cur | last) links&lt;br /&gt;
			const firstRevid = h[0].revid;&lt;br /&gt;
			makeFirstColumnLinks = function (currentRevision) {&lt;br /&gt;
				let result = &#039;(&#039;;&lt;br /&gt;
				result +=&lt;br /&gt;
					&#039;&amp;lt;a href=&amp;quot;&#039; +&lt;br /&gt;
					pg.wiki.titlebase +&lt;br /&gt;
					new Title(curart).urlString() +&lt;br /&gt;
					&#039;&amp;amp;diff=&#039; +&lt;br /&gt;
					firstRevid +&lt;br /&gt;
					&#039;&amp;amp;oldid=&#039; +&lt;br /&gt;
					currentRevision.revid +&lt;br /&gt;
					&#039;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
					popupString(&#039;cur&#039;) +&lt;br /&gt;
					&#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
				result += &#039;&amp;amp;nbsp;|&amp;amp;nbsp;&#039;;&lt;br /&gt;
				result +=&lt;br /&gt;
					&#039;&amp;lt;a href=&amp;quot;&#039; +&lt;br /&gt;
					pg.wiki.titlebase +&lt;br /&gt;
					new Title(curart).urlString() +&lt;br /&gt;
					&#039;&amp;amp;diff=prev&amp;amp;oldid=&#039; +&lt;br /&gt;
					currentRevision.revid +&lt;br /&gt;
					&#039;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
					popupString(&#039;last&#039;) +&lt;br /&gt;
					&#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
				result += &#039;)&#039;;&lt;br /&gt;
				return result;&lt;br /&gt;
			};&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		for (let i = 0; i &amp;lt; h.length; ++i) {&lt;br /&gt;
			if (reallyContribs) {&lt;br /&gt;
				page = h[i].title;&lt;br /&gt;
				curart = new Title(page);&lt;br /&gt;
			}&lt;br /&gt;
			const minor = h[i].minor ? &#039;&amp;lt;b&amp;gt;m &amp;lt;/b&amp;gt;&#039; : &#039;&#039;;&lt;br /&gt;
			const editDate = new Date(h[i].timestamp);&lt;br /&gt;
			let thisDay = formattedDate(editDate);&lt;br /&gt;
			const thisTime = formattedTime(editDate);&lt;br /&gt;
			if (thisDay == day) {&lt;br /&gt;
				thisDay = &#039;&#039;;&lt;br /&gt;
			} else {&lt;br /&gt;
				day = thisDay;&lt;br /&gt;
			}&lt;br /&gt;
			if (thisDay) {&lt;br /&gt;
				html.push(&lt;br /&gt;
					&#039;&amp;lt;tr&amp;gt;&amp;lt;td colspan=3&amp;gt;&amp;lt;span class=&amp;quot;popup_history_date&amp;quot;&amp;gt;&#039; + thisDay + &#039;&amp;lt;/span&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&#039;&lt;br /&gt;
				);&lt;br /&gt;
			}&lt;br /&gt;
			html.push(&#039;&amp;lt;tr class=&amp;quot;popup_history_row_&#039; + (i % 2 ? &#039;odd&#039; : &#039;even&#039;) + &#039;&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
			html.push(&#039;&amp;lt;td&amp;gt;&#039; + makeFirstColumnLinks(h[i]) + &#039;&amp;lt;/td&amp;gt;&#039;);&lt;br /&gt;
			html.push(&lt;br /&gt;
				&#039;&amp;lt;td&amp;gt;&#039; +&lt;br /&gt;
					&#039;&amp;lt;a href=&amp;quot;&#039; +&lt;br /&gt;
					pg.wiki.titlebase +&lt;br /&gt;
					new Title(curart).urlString() +&lt;br /&gt;
					&#039;&amp;amp;oldid=&#039; +&lt;br /&gt;
					h[i].revid +&lt;br /&gt;
					&#039;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
					thisTime +&lt;br /&gt;
					&#039;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&#039;&lt;br /&gt;
			);&lt;br /&gt;
			let col3url = &#039;&#039;,&lt;br /&gt;
				col3txt = &#039;&#039;;&lt;br /&gt;
			if (!reallyContribs) {&lt;br /&gt;
				const user = h[i].user;&lt;br /&gt;
				if (!h[i].userhidden) {&lt;br /&gt;
					if (pg.re.ipUser.test(user)) {&lt;br /&gt;
						col3url =&lt;br /&gt;
							pg.wiki.titlebase +&lt;br /&gt;
							mw.config.get(&#039;wgFormattedNamespaces&#039;)[pg.nsSpecialId] +&lt;br /&gt;
							&#039;:Contributions&amp;amp;target=&#039; +&lt;br /&gt;
							new Title(user).urlString();&lt;br /&gt;
					} else {&lt;br /&gt;
						col3url =&lt;br /&gt;
							pg.wiki.titlebase +&lt;br /&gt;
							mw.config.get(&#039;wgFormattedNamespaces&#039;)[pg.nsUserId] +&lt;br /&gt;
							&#039;:&#039; +&lt;br /&gt;
							new Title(user).urlString();&lt;br /&gt;
					}&lt;br /&gt;
					col3txt = pg.escapeQuotesHTML(user);&lt;br /&gt;
				} else {&lt;br /&gt;
					col3url = getValueOf(&#039;popupRevDelUrl&#039;);&lt;br /&gt;
					col3txt = pg.escapeQuotesHTML(popupString(&#039;revdel&#039;));&lt;br /&gt;
				}&lt;br /&gt;
			} else {&lt;br /&gt;
				col3url = pg.wiki.titlebase + curart.urlString();&lt;br /&gt;
				col3txt = pg.escapeQuotesHTML(page);&lt;br /&gt;
			}&lt;br /&gt;
			html.push(&lt;br /&gt;
				&#039;&amp;lt;td&amp;gt;&#039; +&lt;br /&gt;
					(reallyContribs ? minor : &#039;&#039;) +&lt;br /&gt;
					&#039;&amp;lt;a href=&amp;quot;&#039; +&lt;br /&gt;
					col3url +&lt;br /&gt;
					&#039;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
					col3txt +&lt;br /&gt;
					&#039;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&#039;&lt;br /&gt;
			);&lt;br /&gt;
			let comment = &#039;&#039;;&lt;br /&gt;
			const c = h[i].comment || ( typeof h[i].slots !== &#039;undefined&#039; ? h[i].slots.main.content : null );&lt;br /&gt;
			if (c) {&lt;br /&gt;
				comment = new Previewmaker(c, new Title(curart).toUrl()).editSummaryPreview();&lt;br /&gt;
			} else if (h[i].commenthidden) {&lt;br /&gt;
				comment = popupString(&#039;revdel&#039;);&lt;br /&gt;
			}&lt;br /&gt;
			html.push(&#039;&amp;lt;td&amp;gt;&#039; + (!reallyContribs ? minor : &#039;&#039;) + comment + &#039;&amp;lt;/td&amp;gt;&#039;);&lt;br /&gt;
			html.push(&#039;&amp;lt;/tr&amp;gt;&#039;);&lt;br /&gt;
			html = [html.join(&#039;&#039;)];&lt;br /&gt;
		}&lt;br /&gt;
		html.push(&#039;&amp;lt;/table&amp;gt;&#039;);&lt;br /&gt;
		return html.join(&#039;&#039;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function adjustDate(d, offset) {&lt;br /&gt;
		// offset is in minutes&lt;br /&gt;
		const o = offset * 60 * 1000;&lt;br /&gt;
		return new Date(Number(d) + o);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * This relies on the Date parser understanding en-US dates,&lt;br /&gt;
	 * which is pretty safe assumption, but not perfect.&lt;br /&gt;
	 */&lt;br /&gt;
	function convertTimeZone(date, timeZone) {&lt;br /&gt;
		return new Date(date.toLocaleString(&#039;en-US&#039;, { timeZone: timeZone }));&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function formattedDateTime(date) {&lt;br /&gt;
		// fallback for IE11 and unknown timezones&lt;br /&gt;
		if (useTimeOffset()) {&lt;br /&gt;
			return formattedDate(date) + &#039; &#039; + formattedTime(date);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (getMWDateFormat() === &#039;ISO 8601&#039;) {&lt;br /&gt;
			const d2 = convertTimeZone(date, getTimeZone());&lt;br /&gt;
			return (&lt;br /&gt;
				map(zeroFill, [d2.getFullYear(), d2.getMonth() + 1, d2.getDate()]).join(&#039;-&#039;) +&lt;br /&gt;
				&#039;T&#039; +&lt;br /&gt;
				map(zeroFill, [d2.getHours(), d2.getMinutes(), d2.getSeconds()]).join(&#039;:&#039;)&lt;br /&gt;
			);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const options = getValueOf(&#039;popupDateTimeFormatterOptions&#039;);&lt;br /&gt;
		options.timeZone = getTimeZone();&lt;br /&gt;
		return date.toLocaleString(getLocales(), options);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function formattedDate(date) {&lt;br /&gt;
		// fallback for IE11 and unknown timezones&lt;br /&gt;
		if (useTimeOffset()) {&lt;br /&gt;
			// we adjust the UTC time, so we print the adjusted UTC, but not really UTC values&lt;br /&gt;
			var d2 = adjustDate(date, getTimeOffset());&lt;br /&gt;
			return map(zeroFill, [d2.getUTCFullYear(), d2.getUTCMonth() + 1, d2.getUTCDate()]).join(&#039;-&#039;);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (getMWDateFormat() === &#039;ISO 8601&#039;) {&lt;br /&gt;
			var d2 = convertTimeZone(date, getTimeZone());&lt;br /&gt;
			return map(zeroFill, [d2.getFullYear(), d2.getMonth() + 1, d2.getDate()]).join(&#039;-&#039;);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const options = getValueOf(&#039;popupDateFormatterOptions&#039;);&lt;br /&gt;
		options.timeZone = getTimeZone();&lt;br /&gt;
		return date.toLocaleDateString(getLocales(), options);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function formattedTime(date) {&lt;br /&gt;
		// fallback for IE11 and unknown timezones&lt;br /&gt;
		if (useTimeOffset()) {&lt;br /&gt;
			// we adjust the UTC time, so we print the adjusted UTC, but not really UTC values&lt;br /&gt;
			var d2 = adjustDate(date, getTimeOffset());&lt;br /&gt;
			return map(zeroFill, [d2.getUTCHours(), d2.getUTCMinutes(), d2.getUTCSeconds()]).join(&#039;:&#039;);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (getMWDateFormat() === &#039;ISO 8601&#039;) {&lt;br /&gt;
			var d2 = convertTimeZone(date, getTimeZone());&lt;br /&gt;
			return map(zeroFill, [d2.getHours(), d2.getMinutes(), d2.getSeconds()]).join(&#039;:&#039;);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const options = getValueOf(&#039;popupTimeFormatterOptions&#039;);&lt;br /&gt;
		options.timeZone = getTimeZone();&lt;br /&gt;
		return date.toLocaleTimeString(getLocales(), options);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Get the proper groupnames for the technicalgroups&lt;br /&gt;
	function fetchUserGroupNames(userinfoResponse) {&lt;br /&gt;
		const queryObj = getJsObj(userinfoResponse).query;&lt;br /&gt;
		const user = anyChild(queryObj.users);&lt;br /&gt;
		const messages = [];&lt;br /&gt;
		if (user.groups) {&lt;br /&gt;
			user.groups.forEach((groupName) =&amp;gt; {&lt;br /&gt;
				if ([&#039;*&#039;, &#039;user&#039;, &#039;autoconfirmed&#039;, &#039;extendedconfirmed&#039;, &#039;oathauth-twofactorauth&#039;].indexOf(groupName) === -1) {&lt;br /&gt;
					messages.push(&#039;group-&#039; + groupName + &#039;-member&#039;);&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		}&lt;br /&gt;
		if (queryObj.globaluserinfo &amp;amp;&amp;amp; queryObj.globaluserinfo.groups) {&lt;br /&gt;
			queryObj.globaluserinfo.groups.forEach((groupName) =&amp;gt; {&lt;br /&gt;
				messages.push(&#039;group-&#039; + groupName + &#039;-member&#039;);&lt;br /&gt;
			});&lt;br /&gt;
		}&lt;br /&gt;
		return getMwApi().loadMessagesIfMissing(messages);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function showAPIPreview(queryType, html, id, navpop, download) {&lt;br /&gt;
		// DJ: done&lt;br /&gt;
		let target = &#039;popupPreview&#039;;&lt;br /&gt;
		completedNavpopTask(navpop);&lt;br /&gt;
&lt;br /&gt;
		switch (queryType) {&lt;br /&gt;
			case &#039;imagelinks&#039;:&lt;br /&gt;
			case &#039;category&#039;:&lt;br /&gt;
				target = &#039;popupPostPreview&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;userinfo&#039;:&lt;br /&gt;
				target = &#039;popupUserData&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;revision&#039;:&lt;br /&gt;
				insertPreview(download);&lt;br /&gt;
				return;&lt;br /&gt;
		}&lt;br /&gt;
		setPopupTipsAndHTML(html, target, id);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function APIrevisionPreviewHTML(article, download) {&lt;br /&gt;
		try {&lt;br /&gt;
			const jsObj = getJsObj(download.data);&lt;br /&gt;
			const page = anyChild(jsObj.query.pages);&lt;br /&gt;
			if (page.missing) {&lt;br /&gt;
				// TODO we need to fix this proper later on&lt;br /&gt;
				download.owner = null;&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			const content =&lt;br /&gt;
				page &amp;amp;&amp;amp; page.revisions &amp;amp;&amp;amp; page.revisions[0] &amp;amp;&amp;amp;&lt;br /&gt;
				page.revisions[0].slots &amp;amp;&amp;amp; page.revisions[0].slots.main &amp;amp;&amp;amp;&lt;br /&gt;
				page.revisions[0].slots.main.contentmodel === &#039;wikitext&#039; ?&lt;br /&gt;
					page.revisions[0].slots.main.content :&lt;br /&gt;
					null;&lt;br /&gt;
			if (typeof content === &#039;string&#039;) {&lt;br /&gt;
				download.data = content;&lt;br /&gt;
				download.lastModified = new Date(page.revisions[0].timestamp);&lt;br /&gt;
			}&lt;br /&gt;
			if (page.pageprops.wikibase_item) {&lt;br /&gt;
				download.wikibaseItem = page.pageprops.wikibase_item;&lt;br /&gt;
				download.wikibaseRepo = jsObj.query.wikibase.repo.url.base +&lt;br /&gt;
										jsObj.query.wikibase.repo.url.articlepath;&lt;br /&gt;
			}&lt;br /&gt;
		} catch (someError) {&lt;br /&gt;
			return &#039;Revision preview failed :(&#039;;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function APIbacklinksPreviewHTML(article, download /*, navpop*/) {&lt;br /&gt;
		try {&lt;br /&gt;
			const jsObj = getJsObj(download.data);&lt;br /&gt;
			const list = jsObj.query.backlinks;&lt;br /&gt;
&lt;br /&gt;
			let html = [];&lt;br /&gt;
			if (!list) {&lt;br /&gt;
				return popupString(&#039;No backlinks found&#039;);&lt;br /&gt;
			}&lt;br /&gt;
			for (let i = 0; i &amp;lt; list.length; i++) {&lt;br /&gt;
				const t = new Title(list[i].title);&lt;br /&gt;
				html.push(&lt;br /&gt;
					&#039;&amp;lt;a href=&amp;quot;&#039; + pg.wiki.titlebase + t.urlString() + &#039;&amp;quot;&amp;gt;&#039; + t.toString().entify() + &#039;&amp;lt;/a&amp;gt;&#039;&lt;br /&gt;
				);&lt;br /&gt;
			}&lt;br /&gt;
			html = html.join(&#039;, &#039;);&lt;br /&gt;
			if (jsObj.continue &amp;amp;&amp;amp; jsObj.continue.blcontinue) {&lt;br /&gt;
				html += popupString(&#039; and more&#039;);&lt;br /&gt;
			}&lt;br /&gt;
			return html;&lt;br /&gt;
		} catch (someError) {&lt;br /&gt;
			return &#039;backlinksPreviewHTML went wonky&#039;;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	pg.fn.APIsharedImagePagePreviewHTML = function APIsharedImagePagePreviewHTML(obj) {&lt;br /&gt;
		log(&#039;APIsharedImagePagePreviewHTML&#039;);&lt;br /&gt;
		const popupid = obj.requestid;&lt;br /&gt;
		if (obj.query &amp;amp;&amp;amp; obj.query.pages) {&lt;br /&gt;
			const page = anyChild(obj.query.pages);&lt;br /&gt;
			const content =&lt;br /&gt;
				page &amp;amp;&amp;amp; page.revisions &amp;amp;&amp;amp; page.revisions[0] &amp;amp;&amp;amp;&lt;br /&gt;
				page.revisions[0].slots &amp;amp;&amp;amp; page.revisions[0].slots.main &amp;amp;&amp;amp;&lt;br /&gt;
				page.revisions[0].slots.main.contentmodel === &#039;wikitext&#039; ?&lt;br /&gt;
					page.revisions[0].slots.main.content :&lt;br /&gt;
					null;&lt;br /&gt;
			if (&lt;br /&gt;
				typeof content === &#039;string&#039; &amp;amp;&amp;amp;&lt;br /&gt;
				pg &amp;amp;&amp;amp;&lt;br /&gt;
				pg.current &amp;amp;&amp;amp;&lt;br /&gt;
				pg.current.link &amp;amp;&amp;amp;&lt;br /&gt;
				pg.current.link.navpopup&lt;br /&gt;
			) {&lt;br /&gt;
				/* Not entirely safe, but the best we can do */&lt;br /&gt;
				const p = new Previewmaker(&lt;br /&gt;
					content,&lt;br /&gt;
					pg.current.link.navpopup.article,&lt;br /&gt;
					pg.current.link.navpopup&lt;br /&gt;
				);&lt;br /&gt;
				p.makePreview();&lt;br /&gt;
				setPopupHTML(p.html, &#039;popupSecondPreview&#039;, popupid);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function APIimagepagePreviewHTML(article, download, navpop) {&lt;br /&gt;
		try {&lt;br /&gt;
			const jsObj = getJsObj(download.data);&lt;br /&gt;
			const page = anyChild(jsObj.query.pages);&lt;br /&gt;
			const content =&lt;br /&gt;
				page &amp;amp;&amp;amp; page.revisions &amp;amp;&amp;amp; page.revisions[0] &amp;amp;&amp;amp;&lt;br /&gt;
				page.revisions[0].slots &amp;amp;&amp;amp; page.revisions[0].slots.main &amp;amp;&amp;amp;&lt;br /&gt;
				page.revisions[0].slots.main.contentmodel === &#039;wikitext&#039; ?&lt;br /&gt;
					page.revisions[0].slots.main.content :&lt;br /&gt;
					null;&lt;br /&gt;
			let ret = &#039;&#039;;&lt;br /&gt;
			let alt = &#039;&#039;;&lt;br /&gt;
			try {&lt;br /&gt;
				alt = navpop.parentAnchor.childNodes[0].alt;&lt;br /&gt;
			} catch (e) {}&lt;br /&gt;
			if (alt) {&lt;br /&gt;
				ret = ret + &#039;&amp;lt;hr /&amp;gt;&amp;lt;b&amp;gt;&#039; + popupString(&#039;Alt text:&#039;) + &#039;&amp;lt;/b&amp;gt; &#039; + pg.escapeQuotesHTML(alt);&lt;br /&gt;
			}&lt;br /&gt;
			if (typeof content === &#039;string&#039;) {&lt;br /&gt;
				const p = prepPreviewmaker(content, article, navpop);&lt;br /&gt;
				p.makePreview();&lt;br /&gt;
				if (p.html) {&lt;br /&gt;
					ret += &#039;&amp;lt;hr /&amp;gt;&#039; + p.html;&lt;br /&gt;
				}&lt;br /&gt;
				if (getValueOf(&#039;popupSummaryData&#039;)) {&lt;br /&gt;
					const info = getPageInfo(content, download);&lt;br /&gt;
					log(info);&lt;br /&gt;
					setPopupTrailer(info, navpop.idNumber);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			if (page &amp;amp;&amp;amp; page.imagerepository == &#039;shared&#039;) {&lt;br /&gt;
				const art = new Title(article);&lt;br /&gt;
				const encart = encodeURIComponent(&#039;File:&#039; + art.stripNamespace());&lt;br /&gt;
				const shared_url =&lt;br /&gt;
					pg.wiki.apicommonsbase +&lt;br /&gt;
					&#039;?format=json&amp;amp;formatversion=2&#039; +&lt;br /&gt;
					&#039;&amp;amp;callback=pg.fn.APIsharedImagePagePreviewHTML&#039; +&lt;br /&gt;
					&#039;&amp;amp;requestid=&#039; +&lt;br /&gt;
					navpop.idNumber +&lt;br /&gt;
					&#039;&amp;amp;action=query&amp;amp;prop=revisions&amp;amp;rvslots=main&amp;amp;rvprop=content&amp;amp;titles=&#039; +&lt;br /&gt;
					encart;&lt;br /&gt;
&lt;br /&gt;
				ret =&lt;br /&gt;
					ret +&lt;br /&gt;
					&#039;&amp;lt;hr /&amp;gt;&#039; +&lt;br /&gt;
					popupString(&#039;Image from Commons&#039;) +&lt;br /&gt;
					&#039;: &amp;lt;a href=&amp;quot;&#039; +&lt;br /&gt;
					pg.wiki.commonsbase +&lt;br /&gt;
					&#039;?title=&#039; +&lt;br /&gt;
					encart +&lt;br /&gt;
					&#039;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
					popupString(&#039;Description page&#039;) +&lt;br /&gt;
					&#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
				mw.loader.load(shared_url);&lt;br /&gt;
			}&lt;br /&gt;
			showAPIPreview(&lt;br /&gt;
				&#039;imagelinks&#039;,&lt;br /&gt;
				APIimagelinksPreviewHTML(article, download),&lt;br /&gt;
				navpop.idNumber,&lt;br /&gt;
				download&lt;br /&gt;
			);&lt;br /&gt;
			return ret;&lt;br /&gt;
		} catch (someError) {&lt;br /&gt;
			return &#039;API imagepage preview failed :(&#039;;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function APIimagelinksPreviewHTML(article, download) {&lt;br /&gt;
		try {&lt;br /&gt;
			const jsobj = getJsObj(download.data);&lt;br /&gt;
			const list = jsobj.query.imageusage;&lt;br /&gt;
			if (list) {&lt;br /&gt;
				const ret = [];&lt;br /&gt;
				for (let i = 0; i &amp;lt; list.length; i++) {&lt;br /&gt;
					ret.push(list[i].title);&lt;br /&gt;
				}&lt;br /&gt;
				if (ret.length === 0) {&lt;br /&gt;
					return popupString(&#039;No image links found&#039;);&lt;br /&gt;
				}&lt;br /&gt;
				return &#039;&amp;lt;h2&amp;gt;&#039; + popupString(&#039;File links&#039;) + &#039;&amp;lt;/h2&amp;gt;&#039; + linkList(ret);&lt;br /&gt;
			} else {&lt;br /&gt;
				return popupString(&#039;No image links found&#039;);&lt;br /&gt;
			}&lt;br /&gt;
		} catch (someError) {&lt;br /&gt;
			return &#039;Image links preview generation failed :(&#039;;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function APIcategoryPreviewHTML(article, download) {&lt;br /&gt;
		try {&lt;br /&gt;
			const jsobj = getJsObj(download.data);&lt;br /&gt;
			const list = jsobj.query.categorymembers;&lt;br /&gt;
			let ret = [];&lt;br /&gt;
			for (let p = 0; p &amp;lt; list.length; p++) {&lt;br /&gt;
				ret.push(list[p].title);&lt;br /&gt;
			}&lt;br /&gt;
			if (ret.length === 0) {&lt;br /&gt;
				return popupString(&#039;Empty category&#039;);&lt;br /&gt;
			}&lt;br /&gt;
			ret = &#039;&amp;lt;h2&amp;gt;&#039; + tprintf(&#039;Category members (%s shown)&#039;, [ret.length]) + &#039;&amp;lt;/h2&amp;gt;&#039; + linkList(ret);&lt;br /&gt;
			if (jsobj.continue &amp;amp;&amp;amp; jsobj.continue.cmcontinue) {&lt;br /&gt;
				ret += popupString(&#039; and more&#039;);&lt;br /&gt;
			}&lt;br /&gt;
			return ret;&lt;br /&gt;
		} catch (someError) {&lt;br /&gt;
			return &#039;Category preview failed :(&#039;;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function APIuserInfoPreviewHTML(article, download) {&lt;br /&gt;
		let ret = [];&lt;br /&gt;
		let queryobj = {};&lt;br /&gt;
		try {&lt;br /&gt;
			queryobj = getJsObj(download.data).query;&lt;br /&gt;
		} catch (someError) {&lt;br /&gt;
			return &#039;Userinfo preview failed :(&#039;;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const user = anyChild(queryobj.users);&lt;br /&gt;
		if (user) {&lt;br /&gt;
			const globaluserinfo = queryobj.globaluserinfo;&lt;br /&gt;
			if (user.invalid === &#039;&#039;) {&lt;br /&gt;
				ret.push(popupString(&#039;Invalid user&#039;));&lt;br /&gt;
			} else if (user.missing === &#039;&#039;) {&lt;br /&gt;
				ret.push(popupString(&#039;Not a registered username&#039;));&lt;br /&gt;
			}&lt;br /&gt;
			if (user.blockedby) {&lt;br /&gt;
				if (user.blockpartial) {&lt;br /&gt;
					ret.push(&#039;&amp;lt;b&amp;gt;&#039; + popupString(&#039;Has blocks&#039;) + &#039;&amp;lt;/b&amp;gt;&#039;);&lt;br /&gt;
				} else {&lt;br /&gt;
					ret.push(&#039;&amp;lt;b&amp;gt;&#039; + popupString(&#039;BLOCKED&#039;) + &#039;&amp;lt;/b&amp;gt;&#039;);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			if (globaluserinfo &amp;amp;&amp;amp; (&#039;locked&#039; in globaluserinfo || &#039;hidden&#039; in globaluserinfo)) {&lt;br /&gt;
				let lockedSulAccountIsAttachedToThis = true;&lt;br /&gt;
				for (let i = 0; globaluserinfo.unattached &amp;amp;&amp;amp; i &amp;lt; globaluserinfo.unattached.length; i++) {&lt;br /&gt;
					if (globaluserinfo.unattached[i].wiki === mw.config.get(&#039;wgDBname&#039;)) {&lt;br /&gt;
						lockedSulAccountIsAttachedToThis = false;&lt;br /&gt;
						break;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				if (lockedSulAccountIsAttachedToThis) {&lt;br /&gt;
					if (&#039;locked&#039; in globaluserinfo) {&lt;br /&gt;
						ret.push(&#039;&amp;lt;b&amp;gt;&amp;lt;i&amp;gt;&#039; + popupString(&#039;LOCKED&#039;) + &#039;&amp;lt;/i&amp;gt;&amp;lt;/b&amp;gt;&#039;);&lt;br /&gt;
					}&lt;br /&gt;
					if (&#039;hidden&#039; in globaluserinfo) {&lt;br /&gt;
						ret.push(&#039;&amp;lt;b&amp;gt;&amp;lt;i&amp;gt;&#039; + popupString(&#039;HIDDEN&#039;) + &#039;&amp;lt;/i&amp;gt;&amp;lt;/b&amp;gt;&#039;);&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			if (getValueOf(&#039;popupShowGender&#039;) &amp;amp;&amp;amp; user.gender) {&lt;br /&gt;
				switch (user.gender) {&lt;br /&gt;
					case &#039;male&#039;:&lt;br /&gt;
						ret.push(popupString(&#039;he/him&#039;) + &#039; · &#039;);&lt;br /&gt;
						break;&lt;br /&gt;
					case &#039;female&#039;:&lt;br /&gt;
						ret.push(popupString(&#039;she/her&#039;) + &#039; · &#039;);&lt;br /&gt;
						break;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			if (user.groups) {&lt;br /&gt;
				user.groups.forEach((groupName) =&amp;gt; {&lt;br /&gt;
					if ([&#039;*&#039;, &#039;user&#039;, &#039;autoconfirmed&#039;, &#039;extendedconfirmed&#039;, &#039;oathauth-twofactorauth&#039;].indexOf(groupName) === -1) {&lt;br /&gt;
						ret.push(&lt;br /&gt;
							pg.escapeQuotesHTML(mw.message(&#039;group-&#039; + groupName + &#039;-member&#039;, user.gender).text())&lt;br /&gt;
						);&lt;br /&gt;
					}&lt;br /&gt;
				});&lt;br /&gt;
			}&lt;br /&gt;
			if (globaluserinfo &amp;amp;&amp;amp; globaluserinfo.groups) {&lt;br /&gt;
				globaluserinfo.groups.forEach((groupName) =&amp;gt; {&lt;br /&gt;
					ret.push(&lt;br /&gt;
						&#039;&amp;lt;i&amp;gt;&#039; +&lt;br /&gt;
							pg.escapeQuotesHTML(&lt;br /&gt;
								mw.message(&#039;group-&#039; + groupName + &#039;-member&#039;, user.gender).text()&lt;br /&gt;
							) +&lt;br /&gt;
							&#039;&amp;lt;/i&amp;gt;&#039;&lt;br /&gt;
					);&lt;br /&gt;
				});&lt;br /&gt;
			}&lt;br /&gt;
			if (user.registration) {&lt;br /&gt;
				ret.push(&lt;br /&gt;
					pg.escapeQuotesHTML(&lt;br /&gt;
						(user.editcount ? user.editcount : &#039;0&#039;) +&lt;br /&gt;
							popupString(&#039; edits since: &#039;) +&lt;br /&gt;
							(user.registration ? formattedDate(new Date(user.registration)) : &#039;&#039;)&lt;br /&gt;
					)&lt;br /&gt;
				);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (queryobj.usercontribs &amp;amp;&amp;amp; queryobj.usercontribs.length) {&lt;br /&gt;
			ret.push(&lt;br /&gt;
				popupString(&#039;last edit on &#039;) + formattedDate(new Date(queryobj.usercontribs[0].timestamp))&lt;br /&gt;
			);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (queryobj.blocks) {&lt;br /&gt;
			ret.push(popupString(&#039;IP user&#039;)); //we only request list=blocks for IPs&lt;br /&gt;
			for (let l = 0; l &amp;lt; queryobj.blocks.length; l++) {&lt;br /&gt;
				let rbstr =&lt;br /&gt;
					queryobj.blocks[l].rangestart === queryobj.blocks[l].rangeend ? &#039;BLOCK&#039; : &#039;RANGEBLOCK&#039;;&lt;br /&gt;
				rbstr = !Array.isArray(queryobj.blocks[l].restrictions) ?&lt;br /&gt;
					&#039;Has &#039; + rbstr.toLowerCase() + &#039;s&#039; :&lt;br /&gt;
					rbstr + &#039;ED&#039;;&lt;br /&gt;
				ret.push(&#039;&amp;lt;b&amp;gt;&#039; + popupString(rbstr) + &#039;&amp;lt;/b&amp;gt;&#039;);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// if any element of ret ends with &#039; · &#039;, merge it with the next element to avoid&lt;br /&gt;
		// the .join(&#039;, &#039;) call inserting a comma after it&lt;br /&gt;
		for (let m = 0; m &amp;lt; ret.length - 1; m++) {&lt;br /&gt;
			if (ret[m].length &amp;gt; 3 &amp;amp;&amp;amp; ret[m].substring(ret[m].length - 3) === &#039; · &#039;) {&lt;br /&gt;
				ret[m] = ret[m] + ret[m + 1];&lt;br /&gt;
				ret.splice(m + 1, 1); // delete element at index m+1&lt;br /&gt;
				m--;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		ret = &#039;&amp;lt;hr /&amp;gt;&#039; + ret.join(&#039;, &#039;);&lt;br /&gt;
		return ret;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function APIcontribsPreviewHTML(article, download, navpop) {&lt;br /&gt;
		return APIhistoryPreviewHTML(article, download, navpop, true);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function APIhistoryPreviewHTML(article, download, navpop, reallyContribs) {&lt;br /&gt;
		try {&lt;br /&gt;
			const jsobj = getJsObj(download.data);&lt;br /&gt;
			let edits = [];&lt;br /&gt;
			if (reallyContribs) {&lt;br /&gt;
				edits = jsobj.query.usercontribs;&lt;br /&gt;
			} else {&lt;br /&gt;
				edits = anyChild(jsobj.query.pages).revisions;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			const ret = editPreviewTable(article, edits, reallyContribs);&lt;br /&gt;
			return ret;&lt;br /&gt;
		} catch (someError) {&lt;br /&gt;
			return popupString(&#039;History preview failed&#039;);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ENDFILE: querypreview.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: debug.js&lt;br /&gt;
	////////////////////////////////////////////////////////////////////&lt;br /&gt;
	// Debugging functions&lt;br /&gt;
	////////////////////////////////////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
	function setupDebugging() {&lt;br /&gt;
		if (window.popupDebug) {&lt;br /&gt;
			// popupDebug is set from .version&lt;br /&gt;
			window.log = function (x) {&lt;br /&gt;
				//if(gMsg!=&#039;&#039;)gMsg += &#039;\n&#039;; gMsg+=time() + &#039; &#039; + x; };&lt;br /&gt;
				window.console.log(x);&lt;br /&gt;
			};&lt;br /&gt;
			window.errlog = function (x) {&lt;br /&gt;
				window.console.error(x);&lt;br /&gt;
			};&lt;br /&gt;
			log(&#039;Initializing logger&#039;);&lt;br /&gt;
		} else {&lt;br /&gt;
			window.log = function () {};&lt;br /&gt;
			window.errlog = function () {};&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	// ENDFILE: debug.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: images.js&lt;br /&gt;
&lt;br /&gt;
	// load image of type Title.&lt;br /&gt;
	function loadImage(image, navpop) {&lt;br /&gt;
		if (typeof image.stripNamespace != &#039;function&#039;) {&lt;br /&gt;
			alert(&#039;loadImages bad&#039;);&lt;br /&gt;
		}&lt;br /&gt;
		// API call to retrieve image info.&lt;br /&gt;
&lt;br /&gt;
		if (!getValueOf(&#039;popupImages&#039;)) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (!isValidImageName(image)) {&lt;br /&gt;
			return false;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const art = image.urlString();&lt;br /&gt;
&lt;br /&gt;
		let url = pg.wiki.apiwikibase + &#039;?format=json&amp;amp;formatversion=2&amp;amp;action=query&#039;;&lt;br /&gt;
		url += &#039;&amp;amp;prop=imageinfo&amp;amp;iiprop=url|mime&amp;amp;iiurlwidth=&#039; + getValueOf(&#039;popupImageSizeLarge&#039;);&lt;br /&gt;
		url += &#039;&amp;amp;titles=&#039; + art;&lt;br /&gt;
&lt;br /&gt;
		pendingNavpopTask(navpop);&lt;br /&gt;
		const callback = function (d) {&lt;br /&gt;
			popupsInsertImage(navpop.idNumber, navpop, d);&lt;br /&gt;
		};&lt;br /&gt;
		const go = function () {&lt;br /&gt;
			getPageWithCaching(url, callback, navpop);&lt;br /&gt;
			return true;&lt;br /&gt;
		};&lt;br /&gt;
		if (navpop.visible || !getValueOf(&#039;popupLazyDownloads&#039;)) {&lt;br /&gt;
			go();&lt;br /&gt;
		} else {&lt;br /&gt;
			navpop.addHook(go, &#039;unhide&#039;, &#039;after&#039;, &#039;DOWNLOAD_IMAGE_QUERY_DATA&#039;);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function popupsInsertImage(id, navpop, download) {&lt;br /&gt;
		log(&#039;popupsInsertImage&#039;);&lt;br /&gt;
		let imageinfo;&lt;br /&gt;
		try {&lt;br /&gt;
			const jsObj = getJsObj(download.data);&lt;br /&gt;
			const imagepage = anyChild(jsObj.query.pages);&lt;br /&gt;
			if (typeof imagepage.imageinfo === &#039;undefined&#039;) {&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			imageinfo = imagepage.imageinfo[0];&lt;br /&gt;
		} catch (someError) {&lt;br /&gt;
			log(&#039;popupsInsertImage failed :(&#039;);&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const popupImage = document.getElementById(&#039;popupImg&#039; + id);&lt;br /&gt;
		if (!popupImage) {&lt;br /&gt;
			log(&#039;could not find insertion point for image&#039;);&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		popupImage.width = getValueOf(&#039;popupImageSize&#039;);&lt;br /&gt;
		popupImage.style.display = &#039;inline&#039;;&lt;br /&gt;
&lt;br /&gt;
		// Set the source for the image.&lt;br /&gt;
		if (imageinfo.thumburl) {&lt;br /&gt;
			popupImage.src = imageinfo.thumburl;&lt;br /&gt;
		} else if (imageinfo.mime.indexOf(&#039;image&#039;) === 0) {&lt;br /&gt;
			popupImage.src = imageinfo.url;&lt;br /&gt;
			log(&#039;a thumb could not be found, using original image&#039;);&lt;br /&gt;
		} else {&lt;br /&gt;
			log(&amp;quot;fullsize imagethumb, but not sure if it&#039;s an image&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const a = document.getElementById(&#039;popupImageLink&#039; + id);&lt;br /&gt;
		if (a === null) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Determine the action of the surrouding imagelink.&lt;br /&gt;
		switch (getValueOf(&#039;popupThumbAction&#039;)) {&lt;br /&gt;
			case &#039;imagepage&#039;:&lt;br /&gt;
				if (pg.current.article.namespaceId() != pg.nsImageId) {&lt;br /&gt;
					a.href = imageinfo.descriptionurl;&lt;br /&gt;
					// FIXME: unreliable pg.idNumber&lt;br /&gt;
					popTipsSoonFn(&#039;popupImage&#039; + id)();&lt;br /&gt;
					break;&lt;br /&gt;
				}&lt;br /&gt;
			/* falls through */&lt;br /&gt;
			case &#039;sizetoggle&#039;:&lt;br /&gt;
				a.onclick = toggleSize;&lt;br /&gt;
				a.title = popupString(&#039;Toggle image size&#039;);&lt;br /&gt;
				return;&lt;br /&gt;
			case &#039;linkfull&#039;:&lt;br /&gt;
				a.href = imageinfo.url;&lt;br /&gt;
				a.title = popupString(&#039;Open full-size image&#039;);&lt;br /&gt;
				return;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Toggles the image between inline small and navpop fullwidth.&lt;br /&gt;
	// It&#039;s the same image, no actual sizechange occurs, only display width.&lt;br /&gt;
	function toggleSize() {&lt;br /&gt;
		const imgContainer = this;&lt;br /&gt;
		if (!imgContainer) {&lt;br /&gt;
			alert(&#039;imgContainer is null :/&#039;);&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		const img = imgContainer.firstChild;&lt;br /&gt;
		if (!img) {&lt;br /&gt;
			alert(&#039;img is null :/&#039;);&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (!img.style.width || img.style.width === &#039;&#039;) {&lt;br /&gt;
			img.style.width = &#039;100%&#039;;&lt;br /&gt;
		} else {&lt;br /&gt;
			img.style.width = &#039;&#039;;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Returns one title of an image from wikiText.&lt;br /&gt;
	function getValidImageFromWikiText(wikiText) {&lt;br /&gt;
		// nb in pg.re.image we&#039;re interested in the second bracketed expression&lt;br /&gt;
		// this may change if the regex changes :-(&lt;br /&gt;
		//var match=pg.re.image.exec(wikiText);&lt;br /&gt;
		let matched = null;&lt;br /&gt;
		let match;&lt;br /&gt;
		// strip html comments, used by evil bots :-(&lt;br /&gt;
		const t = removeMatchesUnless(&lt;br /&gt;
			wikiText,&lt;br /&gt;
			/(&amp;lt;!--[\s\S]*?--&amp;gt;)/,&lt;br /&gt;
			1,&lt;br /&gt;
			/^&amp;lt;!--[^[]*popup/i&lt;br /&gt;
		);&lt;br /&gt;
&lt;br /&gt;
		while ((match = pg.re.image.exec(t))) {&lt;br /&gt;
			// now find a sane image name - exclude templates by seeking {&lt;br /&gt;
			const m = match[2] || match[6];&lt;br /&gt;
			if (isValidImageName(m)) {&lt;br /&gt;
				matched = m;&lt;br /&gt;
				break;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		pg.re.image.lastIndex = 0;&lt;br /&gt;
		if (!matched) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
		return mw.config.get(&#039;wgFormattedNamespaces&#039;)[pg.nsImageId] + &#039;:&#039; + upcaseFirst(matched);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function removeMatchesUnless(str, re1, parencount, re2) {&lt;br /&gt;
		const split = str.parenSplit(re1);&lt;br /&gt;
		const c = parencount + 1;&lt;br /&gt;
		for (let i = 0; i &amp;lt; split.length; ++i) {&lt;br /&gt;
			if (i % c === 0 || re2.test(split[i])) {&lt;br /&gt;
				continue;&lt;br /&gt;
			}&lt;br /&gt;
			split[i] = &#039;&#039;;&lt;br /&gt;
		}&lt;br /&gt;
		return split.join(&#039;&#039;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ENDFILE: images.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: namespaces.js&lt;br /&gt;
	// Set up namespaces and other non-strings.js localization&lt;br /&gt;
	// (currently that means redirs too)&lt;br /&gt;
&lt;br /&gt;
	function setNamespaces() {&lt;br /&gt;
		pg.nsSpecialId = -1;&lt;br /&gt;
		pg.nsMainspaceId = 0;&lt;br /&gt;
		pg.nsImageId = 6;&lt;br /&gt;
		pg.nsUserId = 2;&lt;br /&gt;
		pg.nsUsertalkId = 3;&lt;br /&gt;
		pg.nsCategoryId = 14;&lt;br /&gt;
		pg.nsTemplateId = 10;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function setRedirs() {&lt;br /&gt;
		const r = &#039;redirect&#039;;&lt;br /&gt;
		const R = &#039;REDIRECT&#039;;&lt;br /&gt;
		const redirLists = {&lt;br /&gt;
			ar: [R, &#039;تحويل&#039;],&lt;br /&gt;
			be: [r, &#039;перанакіраваньне&#039;],&lt;br /&gt;
			bg: [r, &#039;пренасочване&#039;, &#039;виж&#039;],&lt;br /&gt;
			bs: [r, &#039;Preusmjeri&#039;, &#039;preusmjeri&#039;, &#039;PREUSMJERI&#039;],&lt;br /&gt;
			bn: [R, &#039;পুনর্নির্দেশ&#039;],&lt;br /&gt;
			cs: [R, &#039;PŘESMĚRUJ&#039;],&lt;br /&gt;
			cy: [r, &#039;ail-cyfeirio&#039;],&lt;br /&gt;
			de: [R, &#039;WEITERLEITUNG&#039;],&lt;br /&gt;
			el: [R, &#039;ΑΝΑΚΑΤΕΥΘΥΝΣΗ&#039;],&lt;br /&gt;
			eo: [R, &#039;ALIDIREKTU&#039;, &#039;ALIDIREKTI&#039;],&lt;br /&gt;
			es: [R, &#039;REDIRECCIÓN&#039;],&lt;br /&gt;
			et: [r, &#039;suuna&#039;],&lt;br /&gt;
			ga: [r, &#039;athsheoladh&#039;],&lt;br /&gt;
			gl: [r, &#039;REDIRECCIÓN&#039;, &#039;REDIRECIONAMENTO&#039;],&lt;br /&gt;
			he: [R, &#039;הפניה&#039;],&lt;br /&gt;
			hu: [R, &#039;ÁTIRÁNYÍTÁS&#039;],&lt;br /&gt;
			is: [r, &#039;tilvísun&#039;, &#039;TILVÍSUN&#039;],&lt;br /&gt;
			it: [R, &#039;RINVIA&#039;, &#039;Rinvia&#039;],&lt;br /&gt;
			ja: [R, &#039;転送&#039;],&lt;br /&gt;
			mk: [r, &#039;пренасочување&#039;, &#039;види&#039;],&lt;br /&gt;
			nds: [r, &#039;wiederleiden&#039;],&lt;br /&gt;
			&#039;nds-nl&#039;: [R, &#039;DEURVERWIEZING&#039;, &#039;DUURVERWIEZING&#039;],&lt;br /&gt;
			nl: [R, &#039;DOORVERWIJZING&#039;],&lt;br /&gt;
			nn: [r, &#039;omdiriger&#039;],&lt;br /&gt;
			pl: [R, &#039;PATRZ&#039;, &#039;PRZEKIERUJ&#039;, &#039;TAM&#039;],&lt;br /&gt;
			pt: [R, &#039;redir&#039;],&lt;br /&gt;
			ru: [R, &#039;ПЕРЕНАПРАВЛЕНИЕ&#039;, &#039;ПЕРЕНАПР&#039;],&lt;br /&gt;
			sk: [r, &#039;presmeruj&#039;],&lt;br /&gt;
			sr: [r, &#039;Преусмери&#039;, &#039;преусмери&#039;, &#039;ПРЕУСМЕРИ&#039;, &#039;Preusmeri&#039;, &#039;preusmeri&#039;, &#039;PREUSMERI&#039;],&lt;br /&gt;
			tr: [R, &#039;YÖNLENDİRME&#039;, &#039;yönlendirme&#039;, &#039;YÖNLENDİR&#039;, &#039;yönlendir&#039;],&lt;br /&gt;
			tt: [R, &#039;yünältü&#039;, &#039;перенаправление&#039;, &#039;перенапр&#039;],&lt;br /&gt;
			uk: [R, &#039;ПЕРЕНАПРАВЛЕННЯ&#039;, &#039;ПЕРЕНАПР&#039;],&lt;br /&gt;
			vi: [r, &#039;đổi&#039;],&lt;br /&gt;
			yi: [R, &#039;ווייטערפירן&#039;],&lt;br /&gt;
			zh: [R, &#039;重定向&#039;], // no comma&lt;br /&gt;
		};&lt;br /&gt;
		const redirList = redirLists[pg.wiki.lang] || [r, R];&lt;br /&gt;
		// Mediawiki is very tolerant about what comes after the #redirect at the start&lt;br /&gt;
		pg.re.redirect = RegExp(&lt;br /&gt;
			&#039;^\\s*[#](&#039; + redirList.join(&#039;|&#039;) + &#039;).*?\\[{2}([^\\|\\]]*)(|[^\\]]*)?\\]{2}\\s*(.*)&#039;,&lt;br /&gt;
			&#039;i&#039;&lt;br /&gt;
		);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function setInterwiki() {&lt;br /&gt;
		if (pg.wiki.wikimedia) {&lt;br /&gt;
			// From https://meta.wikimedia.org/wiki/List_of_Wikipedias&lt;br /&gt;
			//en.wikipedia.org/w/api.php?action=sitematrix&amp;amp;format=json&amp;amp;smtype=language&amp;amp;smlangprop=code&amp;amp;formatversion=2&lt;br /&gt;
			pg.wiki.interwiki =&lt;br /&gt;
				&#039;aa|ab|ace|af|ak|als|am|an|ang|ar|arc|arz|as|ast|av|ay|az|ba|bar|bat-smg|bcl|be|be-x-old|bg|bh|bi|bjn|bm|bn|bo|bpy|br|bs|bug|bxr|ca|cbk-zam|cdo|ce|ceb|ch|cho|chr|chy|ckb|co|cr|crh|cs|csb|cu|cv|cy|da|de|diq|dsb|dv|dz|ee|el|eml|en|eo|es|et|eu|ext|fa|ff|fi|fiu-vro|fj|fo|fr|frp|frr|fur|fy|ga|gag|gan|gd|gl|glk|gn|got|gu|gv|ha|hak|haw|he|hi|hif|ho|hr|hsb|ht|hu|hy|hz|ia|id|ie|ig|ii|ik|ilo|io|is|it|iu|ja|jbo|jv|ka|kaa|kab|kbd|kg|ki|kj|kk|kl|km|kn|ko|koi|kr|krc|ks|ksh|ku|kv|kw|ky|la|lad|lb|lbe|lg|li|lij|lmo|ln|lo|lt|ltg|lv|map-bms|mdf|mg|mh|mhr|mi|mk|ml|mn|mo|mr|mrj|ms|mt|mus|mwl|my|myv|mzn|na|nah|nap|nds|nds-nl|ne|new|ng|nl|nn|no|nov|nrm|nv|ny|oc|om|or|os|pa|pag|pam|pap|pcd|pdc|pfl|pi|pih|pl|pms|pnb|pnt|ps|pt|qu|rm|rmy|rn|ro|roa-rup|roa-tara|ru|rue|rw|sa|sah|sc|scn|sco|sd|se|sg|sh|si|simple|sk|sl|sm|sn|so|sq|sr|srn|ss|st|stq|su|sv|sw|szl|ta|te|tet|tg|th|ti|tk|tl|tn|to|tpi|tr|ts|tt|tum|tw|ty|udm|ug|uk|ur|uz|ve|vec|vi|vls|vo|wa|war|wo|wuu|xal|xh|yi|yo|za|zea|zh|zh-classical|zh-min-nan|zh-yue|zu&#039;;&lt;br /&gt;
			pg.re.interwiki = RegExp(&#039;^&#039; + pg.wiki.interwiki + &#039;:&#039;);&lt;br /&gt;
		} else {&lt;br /&gt;
			pg.wiki.interwiki = null;&lt;br /&gt;
			pg.re.interwiki = /^$/;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// return a regexp pattern matching all variants to write the given namespace&lt;br /&gt;
	function nsRe(namespaceId) {&lt;br /&gt;
		const imageNamespaceVariants = [];&lt;br /&gt;
		$.each(mw.config.get(&#039;wgNamespaceIds&#039;), (_localizedNamespaceLc, _namespaceId) =&amp;gt; {&lt;br /&gt;
			if (_namespaceId != namespaceId) {&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			_localizedNamespaceLc = upcaseFirst(_localizedNamespaceLc);&lt;br /&gt;
			imageNamespaceVariants.push(&lt;br /&gt;
				mw.util.escapeRegExp(_localizedNamespaceLc).split(&#039; &#039;).join(&#039;[ _]&#039;)&lt;br /&gt;
			);&lt;br /&gt;
			imageNamespaceVariants.push(mw.util.escapeRegExp(encodeURI(_localizedNamespaceLc)));&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		return &#039;(?:&#039; + imageNamespaceVariants.join(&#039;|&#039;) + &#039;)&#039;;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function nsReImage() {&lt;br /&gt;
		return nsRe(pg.nsImageId);&lt;br /&gt;
	}&lt;br /&gt;
	// ENDFILE: namespaces.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: selpop.js&lt;br /&gt;
	function getEditboxSelection() {&lt;br /&gt;
		// see http://www.webgurusforum.com/8/12/0&lt;br /&gt;
		let editbox;&lt;br /&gt;
		try {&lt;br /&gt;
			editbox = document.editform.wpTextbox1;&lt;br /&gt;
		} catch (dang) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		// IE, Opera&lt;br /&gt;
		if (document.selection) {&lt;br /&gt;
			return document.selection.createRange().text;&lt;br /&gt;
		}&lt;br /&gt;
		// Mozilla&lt;br /&gt;
		const selStart = editbox.selectionStart;&lt;br /&gt;
		const selEnd = editbox.selectionEnd;&lt;br /&gt;
		return editbox.value.substring(selStart, selEnd);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function doSelectionPopup() {&lt;br /&gt;
		// popup if the selection looks like [[foo|anything afterwards at all&lt;br /&gt;
		// or [[foo|bar]]text without &#039;]]&#039;&lt;br /&gt;
		// or [[foo|bar]]&lt;br /&gt;
		const sel = getEditboxSelection();&lt;br /&gt;
		const open = sel.indexOf(&#039;[[&#039;);&lt;br /&gt;
		const pipe = sel.indexOf(&#039;|&#039;);&lt;br /&gt;
		const close = sel.indexOf(&#039;]]&#039;);&lt;br /&gt;
		if (open == -1 || (pipe == -1 &amp;amp;&amp;amp; close == -1)) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if ((pipe != -1 &amp;amp;&amp;amp; open &amp;gt; pipe) || (close != -1 &amp;amp;&amp;amp; open &amp;gt; close)) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		const article = new Title(sel.substring(open + 2, pipe &amp;lt; 0 ? close : pipe));&lt;br /&gt;
		if (getValueOf(&#039;popupOnEditSelection&#039;) == &#039;boxpreview&#039;) {&lt;br /&gt;
			return doSeparateSelectionPopup(sel, article);&lt;br /&gt;
		}&lt;br /&gt;
		if (close &amp;gt; 0 &amp;amp;&amp;amp; sel.substring(close + 2).indexOf(&#039;[[&#039;) &amp;gt;= 0) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		const a = document.createElement(&#039;a&#039;);&lt;br /&gt;
		a.href = pg.wiki.titlebase + article.urlString();&lt;br /&gt;
		mouseOverWikiLink2(a);&lt;br /&gt;
		if (a.navpopup) {&lt;br /&gt;
			a.navpopup.addHook(&lt;br /&gt;
				() =&amp;gt; {&lt;br /&gt;
					runStopPopupTimer(a.navpopup);&lt;br /&gt;
				},&lt;br /&gt;
				&#039;unhide&#039;,&lt;br /&gt;
				&#039;after&#039;&lt;br /&gt;
			);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function doSeparateSelectionPopup(str, article) {&lt;br /&gt;
		let div = document.getElementById(&#039;selectionPreview&#039;);&lt;br /&gt;
		if (!div) {&lt;br /&gt;
			div = document.createElement(&#039;div&#039;);&lt;br /&gt;
			div.id = &#039;selectionPreview&#039;;&lt;br /&gt;
			try {&lt;br /&gt;
				const box = document.editform.wpTextbox1;&lt;br /&gt;
				box.parentNode.insertBefore(div, box);&lt;br /&gt;
			} catch (error) {&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		const p = prepPreviewmaker(str, article, newNavpopup(document.createElement(&#039;a&#039;), article));&lt;br /&gt;
		p.makePreview();&lt;br /&gt;
		if (p.html) {&lt;br /&gt;
			div.innerHTML = p.html;&lt;br /&gt;
		}&lt;br /&gt;
		div.ranSetupTooltipsAlready = false;&lt;br /&gt;
		popTipsSoonFn(&#039;selectionPreview&#039;)();&lt;br /&gt;
	}&lt;br /&gt;
	// ENDFILE: selpop.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: navpopup.js&lt;br /&gt;
	/**&lt;br /&gt;
	 * @file  Defines two classes: {@link Navpopup} and {@link Mousetracker}.&lt;br /&gt;
	 *&lt;br /&gt;
	 * &amp;lt;code&amp;gt;Navpopup&amp;lt;/code&amp;gt; describes popups: when they appear, where, what&lt;br /&gt;
	 * they look like and so on.&lt;br /&gt;
	 *&lt;br /&gt;
	 * &amp;lt;code&amp;gt;Mousetracker&amp;lt;/code&amp;gt; &amp;quot;captures&amp;quot; the mouse using&lt;br /&gt;
	 * &amp;lt;code&amp;gt;document.onmousemove&amp;lt;/code&amp;gt;.&lt;br /&gt;
	 */&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Creates a new Mousetracker.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @constructor&lt;br /&gt;
	 * @class The Mousetracker class. This monitors mouse movements and manages associated hooks.&lt;br /&gt;
	 */&lt;br /&gt;
	function Mousetracker() {&lt;br /&gt;
		/**&lt;br /&gt;
		 * Interval to regularly run the hooks anyway, in milliseconds.&lt;br /&gt;
		 *&lt;br /&gt;
		 * @type {number}&lt;br /&gt;
		 */&lt;br /&gt;
		this.loopDelay = 400;&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
		 * Timer for the loop.&lt;br /&gt;
		 *&lt;br /&gt;
		 * @type {Timer}&lt;br /&gt;
		 */&lt;br /&gt;
		this.timer = null;&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
		 * Flag - are we switched on?&lt;br /&gt;
		 *&lt;br /&gt;
		 * @type {boolean}&lt;br /&gt;
		 */&lt;br /&gt;
		this.active = false;&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
		 * Flag - are we probably inaccurate, i.e. not reflecting the actual mouse position?&lt;br /&gt;
		 */&lt;br /&gt;
		this.dirty = true;&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
		 * Array of hook functions.&lt;br /&gt;
		 *&lt;br /&gt;
		 * @private&lt;br /&gt;
		 * @type {Array}&lt;br /&gt;
		 */&lt;br /&gt;
		this.hooks = [];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Adds a hook, to be called when we get events.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param {Function} f A function which is called as&lt;br /&gt;
	 * &amp;lt;code&amp;gt;f(x,y)&amp;lt;/code&amp;gt;. It should return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; when it&lt;br /&gt;
	 * wants to be removed, and &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; otherwise.&lt;br /&gt;
	 */&lt;br /&gt;
	Mousetracker.prototype.addHook = function (f) {&lt;br /&gt;
		this.hooks.push(f);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Runs hooks, passing them the x&lt;br /&gt;
	 * and y coords of the mouse.  Hook functions that return true are&lt;br /&gt;
	 * passed to {@link Mousetracker#removeHooks} for removal.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Mousetracker.prototype.runHooks = function () {&lt;br /&gt;
		if (!this.hooks || !this.hooks.length) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		//log(&#039;Mousetracker.runHooks; we got some hooks to run&#039;);&lt;br /&gt;
		let remove = false;&lt;br /&gt;
		const removeObj = {};&lt;br /&gt;
		// this method gets called a LOT -&lt;br /&gt;
		// pre-cache some variables&lt;br /&gt;
		const x = this.x,&lt;br /&gt;
			y = this.y,&lt;br /&gt;
			len = this.hooks.length;&lt;br /&gt;
&lt;br /&gt;
		for (let i = 0; i &amp;lt; len; ++i) {&lt;br /&gt;
			//~ run the hook function, and remove it if it returns true&lt;br /&gt;
			if (this.hooks[i](x, y) === true) {&lt;br /&gt;
				remove = true;&lt;br /&gt;
				removeObj[i] = true;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		if (remove) {&lt;br /&gt;
			this.removeHooks(removeObj);&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Removes hooks.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @private&lt;br /&gt;
	 * @param {Object} removeObj An object whose keys are the index&lt;br /&gt;
	 * numbers of functions for removal, with values that evaluate to true&lt;br /&gt;
	 */&lt;br /&gt;
	Mousetracker.prototype.removeHooks = function (removeObj) {&lt;br /&gt;
		const newHooks = [];&lt;br /&gt;
		const len = this.hooks.length;&lt;br /&gt;
		for (let i = 0; i &amp;lt; len; ++i) {&lt;br /&gt;
			if (!removeObj[i]) {&lt;br /&gt;
				newHooks.push(this.hooks[i]);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		this.hooks = newHooks;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Event handler for mouse wiggles.&lt;br /&gt;
	 * We simply grab the event, set x and y and run the hooks.&lt;br /&gt;
	 * This makes the cpu all hot and bothered :-(&lt;br /&gt;
	 *&lt;br /&gt;
	 * @private&lt;br /&gt;
	 * @param {Event} e Mousemove event&lt;br /&gt;
	 */&lt;br /&gt;
	Mousetracker.prototype.track = function (e) {&lt;br /&gt;
		//~ Apparently this is needed in IE.&lt;br /&gt;
		e = e || window.event;&lt;br /&gt;
		let x, y;&lt;br /&gt;
		if (e) {&lt;br /&gt;
			if (e.pageX) {&lt;br /&gt;
				x = e.pageX;&lt;br /&gt;
				y = e.pageY;&lt;br /&gt;
			} else if (typeof e.clientX != &#039;undefined&#039;) {&lt;br /&gt;
				let left,&lt;br /&gt;
					top,&lt;br /&gt;
					docElt = document.documentElement;&lt;br /&gt;
&lt;br /&gt;
				if (docElt) {&lt;br /&gt;
					left = docElt.scrollLeft;&lt;br /&gt;
				}&lt;br /&gt;
				left = left || document.body.scrollLeft || document.scrollLeft || 0;&lt;br /&gt;
&lt;br /&gt;
				if (docElt) {&lt;br /&gt;
					top = docElt.scrollTop;&lt;br /&gt;
				}&lt;br /&gt;
				top = top || document.body.scrollTop || document.scrollTop || 0;&lt;br /&gt;
&lt;br /&gt;
				x = e.clientX + left;&lt;br /&gt;
				y = e.clientY + top;&lt;br /&gt;
			} else {&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			this.setPosition(x, y);&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Sets the x and y coordinates stored and takes appropriate action,&lt;br /&gt;
	 * running hooks as appropriate.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param {number} x Screen coordinates to set&lt;br /&gt;
	 * @param {number} y Screen coordinates to set&lt;br /&gt;
	 */&lt;br /&gt;
	Mousetracker.prototype.setPosition = function (x, y) {&lt;br /&gt;
		this.x = x;&lt;br /&gt;
		this.y = y;&lt;br /&gt;
		if (this.dirty || this.hooks.length === 0) {&lt;br /&gt;
			this.dirty = false;&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (typeof this.lastHook_x != &#039;number&#039;) {&lt;br /&gt;
			this.lastHook_x = -100;&lt;br /&gt;
			this.lastHook_y = -100;&lt;br /&gt;
		}&lt;br /&gt;
		let diff = (this.lastHook_x - x) * (this.lastHook_y - y);&lt;br /&gt;
		diff = diff &amp;gt;= 0 ? diff : -diff;&lt;br /&gt;
		if (diff &amp;gt; 1) {&lt;br /&gt;
			this.lastHook_x = x;&lt;br /&gt;
			this.lastHook_y = y;&lt;br /&gt;
			if (this.dirty) {&lt;br /&gt;
				this.dirty = false;&lt;br /&gt;
			} else {&lt;br /&gt;
				this.runHooks();&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Sets things in motion, unless they are already that is, registering an event handler on&lt;br /&gt;
	 * &amp;lt;code&amp;gt;document.onmousemove&amp;lt;/code&amp;gt;. A half-hearted attempt is made to preserve the old event&lt;br /&gt;
	 * handler if there is one.&lt;br /&gt;
	 */&lt;br /&gt;
	Mousetracker.prototype.enable = function () {&lt;br /&gt;
		if (this.active) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		this.active = true;&lt;br /&gt;
		//~ Save the current handler for mousemove events. This isn&#039;t too&lt;br /&gt;
		//~ robust, of course.&lt;br /&gt;
		this.savedHandler = document.onmousemove;&lt;br /&gt;
		//~ Gotta save @tt{this} again for the closure, and use apply for&lt;br /&gt;
		//~ the member function.&lt;br /&gt;
		const savedThis = this;&lt;br /&gt;
		document.onmousemove = function (e) {&lt;br /&gt;
			savedThis.track.apply(savedThis, [e]);&lt;br /&gt;
		};&lt;br /&gt;
		if (this.loopDelay) {&lt;br /&gt;
			this.timer = setInterval(() =&amp;gt; {&lt;br /&gt;
				//log(&#039;loop delay in mousetracker is working&#039;);&lt;br /&gt;
				savedThis.runHooks();&lt;br /&gt;
			}, this.loopDelay);&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Disables the tracker, removing the event handler.&lt;br /&gt;
	 */&lt;br /&gt;
	Mousetracker.prototype.disable = function () {&lt;br /&gt;
		if (!this.active) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (typeof this.savedHandler === &#039;function&#039;) {&lt;br /&gt;
			document.onmousemove = this.savedHandler;&lt;br /&gt;
		} else {&lt;br /&gt;
			delete document.onmousemove;&lt;br /&gt;
		}&lt;br /&gt;
		if (this.timer) {&lt;br /&gt;
			clearInterval(this.timer);&lt;br /&gt;
		}&lt;br /&gt;
		this.active = false;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Creates a new Navpopup.&lt;br /&gt;
	 * Gets a UID for the popup and&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param init Contructor object. If &amp;lt;code&amp;gt;init.draggable&amp;lt;/code&amp;gt; is true or absent, the popup becomes draggable.&lt;br /&gt;
	 * @constructor&lt;br /&gt;
	 * @class The Navpopup class. This generates popup hints, and does some management of them.&lt;br /&gt;
	 */&lt;br /&gt;
	function Navpopup(/*init*/) {&lt;br /&gt;
		//alert(&#039;new Navpopup(init)&#039;);&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
		 * UID for each Navpopup instance.&lt;br /&gt;
		 * Read-only.&lt;br /&gt;
		 *&lt;br /&gt;
		 * @type {number}&lt;br /&gt;
		 */&lt;br /&gt;
		this.uid = Navpopup.uid++;&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
		 * Read-only flag for current visibility of the popup.&lt;br /&gt;
		 *&lt;br /&gt;
		 * @type {boolean}&lt;br /&gt;
		 * @private&lt;br /&gt;
		 */&lt;br /&gt;
		this.visible = false;&lt;br /&gt;
&lt;br /&gt;
		/** Flag to be set when we want to cancel a previous request to&lt;br /&gt;
		 * show the popup in a little while.&lt;br /&gt;
		 *&lt;br /&gt;
		 * @private&lt;br /&gt;
		 * @type {boolean}&lt;br /&gt;
		 */&lt;br /&gt;
		this.noshow = false;&lt;br /&gt;
&lt;br /&gt;
		/** Categorised list of hooks.&lt;br /&gt;
		 * @see #runHooks&lt;br /&gt;
		 * @see #addHook&lt;br /&gt;
		 * @private&lt;br /&gt;
		 * @type {Object}&lt;br /&gt;
		 */&lt;br /&gt;
		this.hooks = {&lt;br /&gt;
			create: [],&lt;br /&gt;
			unhide: [],&lt;br /&gt;
			hide: [],&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
		 * list of unique IDs of hook functions, to avoid duplicates&lt;br /&gt;
		 *&lt;br /&gt;
		 * @private&lt;br /&gt;
		 */&lt;br /&gt;
		this.hookIds = {};&lt;br /&gt;
&lt;br /&gt;
		/** List of downloads associated with the popup.&lt;br /&gt;
		 * @private&lt;br /&gt;
		 * @type {Array}&lt;br /&gt;
		 */&lt;br /&gt;
		this.downloads = [];&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
		 * Number of uncompleted downloads.&lt;br /&gt;
		 *&lt;br /&gt;
		 * @type {number}&lt;br /&gt;
		 */&lt;br /&gt;
		this.pending = null;&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
		 * Tolerance in pixels when detecting whether the mouse has left the popup.&lt;br /&gt;
		 *&lt;br /&gt;
		 * @type {number}&lt;br /&gt;
		 */&lt;br /&gt;
		this.fuzz = 5;&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
		 * Flag to toggle running {@link #limitHorizontalPosition} to regulate the popup&#039;s position.&lt;br /&gt;
		 *&lt;br /&gt;
		 * @type {boolean}&lt;br /&gt;
		 */&lt;br /&gt;
		this.constrained = true;&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
		 * The popup width in pixels.&lt;br /&gt;
		 *&lt;br /&gt;
		 * @private&lt;br /&gt;
		 * @type {number}&lt;br /&gt;
		 */&lt;br /&gt;
		this.width = 0;&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
		 * The popup width in pixels.&lt;br /&gt;
		 *&lt;br /&gt;
		 * @private&lt;br /&gt;
		 * @type {number}&lt;br /&gt;
		 */&lt;br /&gt;
		this.height = 0;&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
		 * The main content DIV element.&lt;br /&gt;
		 *&lt;br /&gt;
		 * @type {HTMLDivElement}&lt;br /&gt;
		 */&lt;br /&gt;
		this.mainDiv = null;&lt;br /&gt;
		this.createMainDiv();&lt;br /&gt;
&lt;br /&gt;
		//	if (!init || typeof init.popups_draggable==&#039;undefined&#039; || init.popups_draggable) {&lt;br /&gt;
		//		this.makeDraggable(true);&lt;br /&gt;
		//	}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * A UID for each Navpopup. This constructor property is just a counter.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @type {number}&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Navpopup.uid = 0;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Retrieves the {@link #visible} attribute, indicating whether the popup is currently visible.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @type {boolean}&lt;br /&gt;
	 */&lt;br /&gt;
	Navpopup.prototype.isVisible = function () {&lt;br /&gt;
		return this.visible;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Repositions popup using CSS style.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @private&lt;br /&gt;
	 * @param {number} x x-coordinate (px)&lt;br /&gt;
	 * @param {number} y y-coordinate (px)&lt;br /&gt;
	 * @param {boolean} noLimitHor Don&#039;t call {@link #limitHorizontalPosition}&lt;br /&gt;
	 */&lt;br /&gt;
	Navpopup.prototype.reposition = function (x, y, noLimitHor) {&lt;br /&gt;
		log(&#039;reposition(&#039; + x + &#039;,&#039; + y + &#039;,&#039; + noLimitHor + &#039;)&#039;);&lt;br /&gt;
		if (typeof x != &#039;undefined&#039; &amp;amp;&amp;amp; x !== null) {&lt;br /&gt;
			this.left = x;&lt;br /&gt;
		}&lt;br /&gt;
		if (typeof y != &#039;undefined&#039; &amp;amp;&amp;amp; y !== null) {&lt;br /&gt;
			this.top = y;&lt;br /&gt;
		}&lt;br /&gt;
		if (typeof this.left != &#039;undefined&#039; &amp;amp;&amp;amp; typeof this.top != &#039;undefined&#039;) {&lt;br /&gt;
			this.mainDiv.style.left = this.left + &#039;px&#039;;&lt;br /&gt;
			this.mainDiv.style.top = this.top + &#039;px&#039;;&lt;br /&gt;
		}&lt;br /&gt;
		if (!noLimitHor) {&lt;br /&gt;
			this.limitHorizontalPosition();&lt;br /&gt;
		}&lt;br /&gt;
		//console.log(&#039;navpop&#039;+this.uid+&#039; - (left,top)=(&#039; + this.left + &#039;,&#039; + this.top + &#039;), css=(&#039;&lt;br /&gt;
		//+ this.mainDiv.style.left + &#039;,&#039; + this.mainDiv.style.top + &#039;)&#039;);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Prevents popups from being in silly locations. Hopefully.&lt;br /&gt;
	 * Should not be run if {@link #constrained} is true.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Navpopup.prototype.limitHorizontalPosition = function () {&lt;br /&gt;
		if (!this.constrained || this.tooWide) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		this.updateDimensions();&lt;br /&gt;
		const x = this.left;&lt;br /&gt;
		const w = this.width;&lt;br /&gt;
		const cWidth = document.body.clientWidth;&lt;br /&gt;
&lt;br /&gt;
		//	log(&#039;limitHorizontalPosition: x=&#039;+x+&lt;br /&gt;
		//			&#039;, this.left=&#039; + this.left +&lt;br /&gt;
		//			&#039;, this.width=&#039; + this.width +&lt;br /&gt;
		//			&#039;, cWidth=&#039; + cWidth);&lt;br /&gt;
&lt;br /&gt;
		if (&lt;br /&gt;
			x + w &amp;gt;= cWidth ||&lt;br /&gt;
			(x &amp;gt; 0 &amp;amp;&amp;amp;&lt;br /&gt;
				this.maxWidth &amp;amp;&amp;amp;&lt;br /&gt;
				this.width &amp;lt; this.maxWidth &amp;amp;&amp;amp;&lt;br /&gt;
				this.height &amp;gt; this.width &amp;amp;&amp;amp;&lt;br /&gt;
				x &amp;gt; cWidth - this.maxWidth)&lt;br /&gt;
		) {&lt;br /&gt;
			// This is a very nasty hack. There has to be a better way!&lt;br /&gt;
			// We find the &amp;quot;natural&amp;quot; width of the div by positioning it at the far left&lt;br /&gt;
			// then reset it so that it should be flush right (well, nearly)&lt;br /&gt;
			this.mainDiv.style.left = &#039;-10000px&#039;;&lt;br /&gt;
			this.mainDiv.style.width = this.maxWidth + &#039;px&#039;;&lt;br /&gt;
			const naturalWidth = parseInt(this.mainDiv.offsetWidth, 10);&lt;br /&gt;
			let newLeft = cWidth - naturalWidth - 1;&lt;br /&gt;
			if (newLeft &amp;lt; 0) {&lt;br /&gt;
				newLeft = 0;&lt;br /&gt;
				this.tooWide = true;&lt;br /&gt;
			} // still unstable for really wide popups?&lt;br /&gt;
			log(&lt;br /&gt;
				&#039;limitHorizontalPosition: moving to (&#039; +&lt;br /&gt;
					newLeft +&lt;br /&gt;
					&#039;,&#039; +&lt;br /&gt;
					this.top +&lt;br /&gt;
					&#039;);&#039; +&lt;br /&gt;
					&#039; naturalWidth=&#039; +&lt;br /&gt;
					naturalWidth +&lt;br /&gt;
					&#039;, clientWidth=&#039; +&lt;br /&gt;
					cWidth&lt;br /&gt;
			);&lt;br /&gt;
			this.reposition(newLeft, null, true);&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Counter indicating the z-order of the &amp;quot;highest&amp;quot; popup.&lt;br /&gt;
	 * We start the z-index at 1000 so that popups are above everything&lt;br /&gt;
	 * else on the screen.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @private&lt;br /&gt;
	 * @type {number}&lt;br /&gt;
	 */&lt;br /&gt;
	Navpopup.highest = 1000;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Brings popup to the top of the z-order.&lt;br /&gt;
	 * We increment the {@link #highest} property of the contructor here.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Navpopup.prototype.raise = function () {&lt;br /&gt;
		this.mainDiv.style.zIndex = Navpopup.highest + 1;&lt;br /&gt;
		++Navpopup.highest;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Shows the popup provided {@link #noshow} is not true.&lt;br /&gt;
	 * Updates the position, brings the popup to the top of the z-order and unhides it.&lt;br /&gt;
	 */&lt;br /&gt;
	Navpopup.prototype.show = function () {&lt;br /&gt;
		//document.title+=&#039;s&#039;;&lt;br /&gt;
		if (this.noshow) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		//document.title+=&#039;t&#039;;&lt;br /&gt;
		this.reposition();&lt;br /&gt;
		this.raise();&lt;br /&gt;
		this.unhide();&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Checks to see if the mouse pointer has&lt;br /&gt;
	 * stabilised (checking every &amp;lt;code&amp;gt;time&amp;lt;/code&amp;gt;/2 milliseconds) and runs the&lt;br /&gt;
	 * {@link #show} method if it has.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param {number} time The minimum time (ms) before the popup may be shown.&lt;br /&gt;
	 */&lt;br /&gt;
	Navpopup.prototype.showSoonIfStable = function (time) {&lt;br /&gt;
		log(&#039;showSoonIfStable, time=&#039; + time);&lt;br /&gt;
		if (this.visible) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		this.noshow = false;&lt;br /&gt;
&lt;br /&gt;
		//~ initialize these variables so that we never run @tt{show} after&lt;br /&gt;
		//~ just half the time&lt;br /&gt;
		this.stable_x = -10000;&lt;br /&gt;
		this.stable_y = -10000;&lt;br /&gt;
&lt;br /&gt;
		const stableShow = function () {&lt;br /&gt;
			log(&#039;stableShow called&#039;);&lt;br /&gt;
			let new_x = Navpopup.tracker.x,&lt;br /&gt;
				new_y = Navpopup.tracker.y;&lt;br /&gt;
			let dx = savedThis.stable_x - new_x,&lt;br /&gt;
				dy = savedThis.stable_y - new_y;&lt;br /&gt;
			let fuzz2 = 0; // savedThis.fuzz * savedThis.fuzz;&lt;br /&gt;
			//document.title += &#039;[&#039; + [savedThis.stable_x,new_x, savedThis.stable_y,new_y, dx, dy, fuzz2].join(&#039;,&#039;) + &#039;] &#039;;&lt;br /&gt;
			if (dx * dx &amp;lt;= fuzz2 &amp;amp;&amp;amp; dy * dy &amp;lt;= fuzz2) {&lt;br /&gt;
				log(&#039;mouse is stable&#039;);&lt;br /&gt;
				clearInterval(savedThis.showSoonStableTimer);&lt;br /&gt;
				savedThis.reposition.apply(savedThis, [new_x + 2, new_y + 2]);&lt;br /&gt;
				savedThis.show.apply(savedThis, []);&lt;br /&gt;
				savedThis.limitHorizontalPosition.apply(savedThis, []);&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			savedThis.stable_x = new_x;&lt;br /&gt;
			savedThis.stable_y = new_y;&lt;br /&gt;
		};&lt;br /&gt;
		var savedThis = this;&lt;br /&gt;
		this.showSoonStableTimer = setInterval(stableShow, time / 2);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Sets the {@link #noshow} flag and hides the popup. This should be called&lt;br /&gt;
	 * when the mouse leaves the link before&lt;br /&gt;
	 * (or after) it&#039;s actually been displayed.&lt;br /&gt;
	 */&lt;br /&gt;
	Navpopup.prototype.banish = function () {&lt;br /&gt;
		log(&#039;banish called&#039;);&lt;br /&gt;
		// hide and prevent showing with showSoon in the future&lt;br /&gt;
		this.noshow = true;&lt;br /&gt;
		if (this.showSoonStableTimer) {&lt;br /&gt;
			log(&#039;clearing showSoonStableTimer&#039;);&lt;br /&gt;
			clearInterval(this.showSoonStableTimer);&lt;br /&gt;
		}&lt;br /&gt;
		this.hide();&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Runs hooks added with {@link #addHook}.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @private&lt;br /&gt;
	 * @param {string} key Key name of the {@link #hooks} array - one of &#039;create&#039;, &#039;unhide&#039;, &#039;hide&#039;&lt;br /&gt;
	 * @param {string} when Controls exactly when the hook is run: either &#039;before&#039; or &#039;after&#039;&lt;br /&gt;
	 */&lt;br /&gt;
	Navpopup.prototype.runHooks = function (key, when) {&lt;br /&gt;
		if (!this.hooks[key]) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		const keyHooks = this.hooks[key];&lt;br /&gt;
		const len = keyHooks.length;&lt;br /&gt;
		for (let i = 0; i &amp;lt; len; ++i) {&lt;br /&gt;
			if (keyHooks[i] &amp;amp;&amp;amp; keyHooks[i].when == when) {&lt;br /&gt;
				if (keyHooks[i].hook.apply(this, [])) {&lt;br /&gt;
					// remove the hook&lt;br /&gt;
					if (keyHooks[i].hookId) {&lt;br /&gt;
						delete this.hookIds[keyHooks[i].hookId];&lt;br /&gt;
					}&lt;br /&gt;
					keyHooks[i] = null;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Adds a hook to the popup. Hook functions are run with &amp;lt;code&amp;gt;this&amp;lt;/code&amp;gt; set to refer to the&lt;br /&gt;
	 * Navpopup instance, and no arguments.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param {Function} hook The hook function. Functions that return true are deleted.&lt;br /&gt;
	 * @param {string} key Key name of the {@link #hooks} array - one of &#039;create&#039;, &#039;unhide&#039;, &#039;hide&#039;&lt;br /&gt;
	 * @param {String} when Controls exactly when the hook is run: either &#039;before&#039; or &#039;after&#039;&lt;br /&gt;
	 * @param {String} uid A truthy string identifying the hook function; if it matches another hook&lt;br /&gt;
	 * in this position, it won&#039;t be added again.&lt;br /&gt;
	 */&lt;br /&gt;
	Navpopup.prototype.addHook = function (hook, key, when, uid) {&lt;br /&gt;
		when = when || &#039;after&#039;;&lt;br /&gt;
		if (!this.hooks[key]) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		// if uid is specified, don&#039;t add duplicates&lt;br /&gt;
		let hookId = null;&lt;br /&gt;
		if (uid) {&lt;br /&gt;
			hookId = [key, when, uid].join(&#039;|&#039;);&lt;br /&gt;
			if (this.hookIds[hookId]) {&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			this.hookIds[hookId] = true;&lt;br /&gt;
		}&lt;br /&gt;
		this.hooks[key].push({ hook: hook, when: when, hookId: hookId });&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Creates the main DIV element, which contains all the actual popup content.&lt;br /&gt;
	 * Runs hooks with key &#039;create&#039;.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Navpopup.prototype.createMainDiv = function () {&lt;br /&gt;
		if (this.mainDiv) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		this.runHooks(&#039;create&#039;, &#039;before&#039;);&lt;br /&gt;
		const mainDiv = document.createElement(&#039;div&#039;);&lt;br /&gt;
&lt;br /&gt;
		const savedThis = this;&lt;br /&gt;
		mainDiv.onclick = function (e) {&lt;br /&gt;
			savedThis.onclickHandler(e);&lt;br /&gt;
		};&lt;br /&gt;
		mainDiv.className = this.className ? this.className : &#039;navpopup_maindiv&#039;;&lt;br /&gt;
		mainDiv.id = mainDiv.className + this.uid;&lt;br /&gt;
&lt;br /&gt;
		mainDiv.style.position = &#039;absolute&#039;;&lt;br /&gt;
		mainDiv.style.minWidth = &#039;350px&#039;;&lt;br /&gt;
		mainDiv.style.display = &#039;none&#039;;&lt;br /&gt;
		mainDiv.className = &#039;navpopup&#039;;&lt;br /&gt;
&lt;br /&gt;
		// easy access to javascript object through DOM functions&lt;br /&gt;
		mainDiv.navpopup = this;&lt;br /&gt;
&lt;br /&gt;
		this.mainDiv = mainDiv;&lt;br /&gt;
		document.body.appendChild(mainDiv);&lt;br /&gt;
		this.runHooks(&#039;create&#039;, &#039;after&#039;);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Calls the {@link #raise} method.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Navpopup.prototype.onclickHandler = function (/*e*/) {&lt;br /&gt;
		this.raise();&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Makes the popup draggable, using a {@link Drag} object.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Navpopup.prototype.makeDraggable = function (handleName) {&lt;br /&gt;
		if (!this.mainDiv) {&lt;br /&gt;
			this.createMainDiv();&lt;br /&gt;
		}&lt;br /&gt;
		const drag = new Drag();&lt;br /&gt;
		if (!handleName) {&lt;br /&gt;
			drag.startCondition = function (e) {&lt;br /&gt;
				try {&lt;br /&gt;
					if (!e.shiftKey) {&lt;br /&gt;
						return false;&lt;br /&gt;
					}&lt;br /&gt;
				} catch (err) {&lt;br /&gt;
					return false;&lt;br /&gt;
				}&lt;br /&gt;
				return true;&lt;br /&gt;
			};&lt;br /&gt;
		}&lt;br /&gt;
		let dragHandle;&lt;br /&gt;
		if (handleName) {&lt;br /&gt;
			dragHandle = document.getElementById(handleName);&lt;br /&gt;
		}&lt;br /&gt;
		if (!dragHandle) {&lt;br /&gt;
			dragHandle = this.mainDiv;&lt;br /&gt;
		}&lt;br /&gt;
		const np = this;&lt;br /&gt;
		drag.endHook = function (x, y) {&lt;br /&gt;
			Navpopup.tracker.dirty = true;&lt;br /&gt;
			np.reposition(x, y);&lt;br /&gt;
		};&lt;br /&gt;
		drag.init(dragHandle, this.mainDiv);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Hides the popup using CSS. Runs hooks with key &#039;hide&#039;.&lt;br /&gt;
	 * Sets {@link #visible} appropriately.&lt;br /&gt;
	 * {@link #banish} should be called externally instead of this method.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Navpopup.prototype.hide = function () {&lt;br /&gt;
		this.runHooks(&#039;hide&#039;, &#039;before&#039;);&lt;br /&gt;
		this.abortDownloads();&lt;br /&gt;
		if (typeof this.visible != &#039;undefined&#039; &amp;amp;&amp;amp; this.visible) {&lt;br /&gt;
			this.mainDiv.style.display = &#039;none&#039;;&lt;br /&gt;
			this.visible = false;&lt;br /&gt;
		}&lt;br /&gt;
		this.runHooks(&#039;hide&#039;, &#039;after&#039;);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Shows the popup using CSS. Runs hooks with key &#039;unhide&#039;.&lt;br /&gt;
	 * Sets {@link #visible} appropriately.   {@link #show} should be called externally instead of this method.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Navpopup.prototype.unhide = function () {&lt;br /&gt;
		this.runHooks(&#039;unhide&#039;, &#039;before&#039;);&lt;br /&gt;
		if (typeof this.visible != &#039;undefined&#039; &amp;amp;&amp;amp; !this.visible) {&lt;br /&gt;
			this.mainDiv.style.display = &#039;inline&#039;;&lt;br /&gt;
			this.visible = true;&lt;br /&gt;
		}&lt;br /&gt;
		this.runHooks(&#039;unhide&#039;, &#039;after&#039;);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Sets the &amp;lt;code&amp;gt;innerHTML&amp;lt;/code&amp;gt; attribute of the main div containing the popup content.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param {string} html The HTML to set.&lt;br /&gt;
	 */&lt;br /&gt;
	Navpopup.prototype.setInnerHTML = function (html) {&lt;br /&gt;
		this.mainDiv.innerHTML = html;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Updates the {@link #width} and {@link #height} attributes with the CSS properties.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @private&lt;br /&gt;
	 */&lt;br /&gt;
	Navpopup.prototype.updateDimensions = function () {&lt;br /&gt;
		this.width = parseInt(this.mainDiv.offsetWidth, 10);&lt;br /&gt;
		this.height = parseInt(this.mainDiv.offsetHeight, 10);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Checks if the point (x,y) is within {@link #fuzz} of the&lt;br /&gt;
	 * {@link #mainDiv}.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param {number} x x-coordinate (px)&lt;br /&gt;
	 * @param {number} y y-coordinate (px)&lt;br /&gt;
	 * @type {boolean}&lt;br /&gt;
	 */&lt;br /&gt;
	Navpopup.prototype.isWithin = function (x, y) {&lt;br /&gt;
		//~ If we&#039;re not even visible, no point should be considered as&lt;br /&gt;
		//~ being within the popup.&lt;br /&gt;
		if (!this.visible) {&lt;br /&gt;
			return false;&lt;br /&gt;
		}&lt;br /&gt;
		this.updateDimensions();&lt;br /&gt;
		const fuzz = this.fuzz || 0;&lt;br /&gt;
		//~ Use a simple box metric here.&lt;br /&gt;
		return (&lt;br /&gt;
			x + fuzz &amp;gt;= this.left &amp;amp;&amp;amp;&lt;br /&gt;
			x - fuzz &amp;lt;= this.left + this.width &amp;amp;&amp;amp;&lt;br /&gt;
			y + fuzz &amp;gt;= this.top &amp;amp;&amp;amp;&lt;br /&gt;
			y - fuzz &amp;lt;= this.top + this.height&lt;br /&gt;
		);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Adds a download to {@link #downloads}.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param {Downloader} download&lt;br /&gt;
	 */&lt;br /&gt;
	Navpopup.prototype.addDownload = function (download) {&lt;br /&gt;
		if (!download) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		this.downloads.push(download);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Aborts the downloads listed in {@link #downloads}.&lt;br /&gt;
	 *&lt;br /&gt;
	 * @see Downloader#abort&lt;br /&gt;
	 */&lt;br /&gt;
	Navpopup.prototype.abortDownloads = function () {&lt;br /&gt;
		for (let i = 0; i &amp;lt; this.downloads.length; ++i) {&lt;br /&gt;
			const d = this.downloads[i];&lt;br /&gt;
			if (d &amp;amp;&amp;amp; d.abort) {&lt;br /&gt;
				d.abort();&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		this.downloads = [];&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * A {@link Mousetracker} instance which is a property of the constructor (pseudo-global).&lt;br /&gt;
	 */&lt;br /&gt;
	Navpopup.tracker = new Mousetracker();&lt;br /&gt;
	// ENDFILE: navpopup.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: diff.js&lt;br /&gt;
	/*&lt;br /&gt;
	 * Javascript Diff Algorithm&lt;br /&gt;
	 *  By John Resig (http://ejohn.org/) and [[:en:User:Lupin]]&lt;br /&gt;
	 *&lt;br /&gt;
	 * More Info:&lt;br /&gt;
	 *  http://ejohn.org/projects/javascript-diff-algorithm/&lt;br /&gt;
	 */&lt;br /&gt;
&lt;br /&gt;
	function delFmt(x) {&lt;br /&gt;
		if (!x.length) {&lt;br /&gt;
			return &#039;&#039;;&lt;br /&gt;
		}&lt;br /&gt;
		return &amp;quot;&amp;lt;del class=&#039;popupDiff&#039;&amp;gt;&amp;quot; + x.join(&#039;&#039;) + &#039;&amp;lt;/del&amp;gt;&#039;;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function insFmt(x) {&lt;br /&gt;
		if (!x.length) {&lt;br /&gt;
			return &#039;&#039;;&lt;br /&gt;
		}&lt;br /&gt;
		return &amp;quot;&amp;lt;ins class=&#039;popupDiff&#039;&amp;gt;&amp;quot; + x.join(&#039;&#039;) + &#039;&amp;lt;/ins&amp;gt;&#039;;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function countCrossings(a, b, i, eject) {&lt;br /&gt;
		// count the crossings on the edge starting at b[i]&lt;br /&gt;
		if (!b[i].row &amp;amp;&amp;amp; b[i].row !== 0) {&lt;br /&gt;
			return -1;&lt;br /&gt;
		}&lt;br /&gt;
		let count = 0;&lt;br /&gt;
		for (let j = 0; j &amp;lt; a.length; ++j) {&lt;br /&gt;
			if (!a[j].row &amp;amp;&amp;amp; a[j].row !== 0) {&lt;br /&gt;
				continue;&lt;br /&gt;
			}&lt;br /&gt;
			if ((j - b[i].row) * (i - a[j].row) &amp;gt; 0) {&lt;br /&gt;
				if (eject) {&lt;br /&gt;
					return true;&lt;br /&gt;
				}&lt;br /&gt;
				count++;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return count;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function shortenDiffString(str, context) {&lt;br /&gt;
		const re = /(&amp;lt;del[\s\S]*?&amp;lt;\/del&amp;gt;|&amp;lt;ins[\s\S]*?&amp;lt;\/ins&amp;gt;)/;&lt;br /&gt;
		const splitted = str.parenSplit(re);&lt;br /&gt;
		let ret = [&#039;&#039;];&lt;br /&gt;
		for (let i = 0; i &amp;lt; splitted.length; i += 2) {&lt;br /&gt;
			if (splitted[i].length &amp;lt; 2 * context) {&lt;br /&gt;
				ret[ret.length - 1] += splitted[i];&lt;br /&gt;
				if (i + 1 &amp;lt; splitted.length) {&lt;br /&gt;
					ret[ret.length - 1] += splitted[i + 1];&lt;br /&gt;
				}&lt;br /&gt;
				continue;&lt;br /&gt;
			} else {&lt;br /&gt;
				if (i &amp;gt; 0) {&lt;br /&gt;
					ret[ret.length - 1] += splitted[i].substring(0, context);&lt;br /&gt;
				}&lt;br /&gt;
				if (i + 1 &amp;lt; splitted.length) {&lt;br /&gt;
					ret.push(splitted[i].substring(splitted[i].length - context) + splitted[i + 1]);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		while (ret.length &amp;gt; 0 &amp;amp;&amp;amp; !ret[0]) {&lt;br /&gt;
			ret = ret.slice(1);&lt;br /&gt;
		}&lt;br /&gt;
		return ret;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function diffString(o, n, simpleSplit) {&lt;br /&gt;
		const splitRe = /([[]{2}|[\]]{2}|[{]{2,3}|[}]{2,3}|[|]|=|&amp;lt;|&amp;gt;|[*:]+|\s|\b)/;&lt;br /&gt;
&lt;br /&gt;
		//  We need to split the strings o and n first, and entify() the parts&lt;br /&gt;
		//  individually, so that the HTML entities are never cut apart. (AxelBoldt)&lt;br /&gt;
		let out, i, oSplitted, nSplitted;&lt;br /&gt;
		if (simpleSplit) {&lt;br /&gt;
			oSplitted = o.split(/\b/);&lt;br /&gt;
			nSplitted = n.split(/\b/);&lt;br /&gt;
		} else {&lt;br /&gt;
			oSplitted = o.parenSplit(splitRe);&lt;br /&gt;
			nSplitted = n.parenSplit(splitRe);&lt;br /&gt;
		}&lt;br /&gt;
		for (i = 0; i &amp;lt; oSplitted.length; ++i) {&lt;br /&gt;
			oSplitted[i] = oSplitted[i].entify();&lt;br /&gt;
		}&lt;br /&gt;
		for (i = 0; i &amp;lt; nSplitted.length; ++i) {&lt;br /&gt;
			nSplitted[i] = nSplitted[i].entify();&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		out = diff(oSplitted, nSplitted);&lt;br /&gt;
		let str = &#039;&#039;;&lt;br /&gt;
		let acc = []; // accumulator for prettier output&lt;br /&gt;
&lt;br /&gt;
		// crossing pairings -- eg &#039;A B&#039; vs &#039;B A&#039; -- cause problems, so let&#039;s iron them out&lt;br /&gt;
		// this doesn&#039;t always do things optimally but it should be fast enough&lt;br /&gt;
		let maxOutputPair = 0;&lt;br /&gt;
		for (i = 0; i &amp;lt; out.n.length; ++i) {&lt;br /&gt;
			if (out.n[i].paired) {&lt;br /&gt;
				if (maxOutputPair &amp;gt; out.n[i].row) {&lt;br /&gt;
					// tangle - delete pairing&lt;br /&gt;
					out.o[out.n[i].row] = out.o[out.n[i].row].text;&lt;br /&gt;
					out.n[i] = out.n[i].text;&lt;br /&gt;
				}&lt;br /&gt;
				if (maxOutputPair &amp;lt; out.n[i].row) {&lt;br /&gt;
					maxOutputPair = out.n[i].row;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// output the stuff preceding the first paired old line&lt;br /&gt;
		for (i = 0; i &amp;lt; out.o.length &amp;amp;&amp;amp; !out.o[i].paired; ++i) {&lt;br /&gt;
			acc.push(out.o[i]);&lt;br /&gt;
		}&lt;br /&gt;
		str += delFmt(acc);&lt;br /&gt;
		acc = [];&lt;br /&gt;
&lt;br /&gt;
		// main loop&lt;br /&gt;
		for (i = 0; i &amp;lt; out.n.length; ++i) {&lt;br /&gt;
			// output unpaired new &amp;quot;lines&amp;quot;&lt;br /&gt;
			while (i &amp;lt; out.n.length &amp;amp;&amp;amp; !out.n[i].paired) {&lt;br /&gt;
				acc.push(out.n[i++]);&lt;br /&gt;
			}&lt;br /&gt;
			str += insFmt(acc);&lt;br /&gt;
			acc = [];&lt;br /&gt;
			if (i &amp;lt; out.n.length) {&lt;br /&gt;
				// this new &amp;quot;line&amp;quot; is paired with the (out.n[i].row)th old &amp;quot;line&amp;quot;&lt;br /&gt;
				str += out.n[i].text;&lt;br /&gt;
				// output unpaired old rows starting after this new line&#039;s partner&lt;br /&gt;
				let m = out.n[i].row + 1;&lt;br /&gt;
				while (m &amp;lt; out.o.length &amp;amp;&amp;amp; !out.o[m].paired) {&lt;br /&gt;
					acc.push(out.o[m++]);&lt;br /&gt;
				}&lt;br /&gt;
				str += delFmt(acc);&lt;br /&gt;
				acc = [];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return str;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// see http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Object&lt;br /&gt;
	// FIXME: use obj.hasOwnProperty instead of this kludge!&lt;br /&gt;
	const jsReservedProperties = RegExp(&lt;br /&gt;
		&#039;^(constructor|prototype|__((define|lookup)[GS]etter)__&#039; +&lt;br /&gt;
			&#039;|eval|hasOwnProperty|propertyIsEnumerable&#039; +&lt;br /&gt;
			&#039;|to(Source|String|LocaleString)|(un)?watch|valueOf)$&#039;&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	function diffBugAlert(word) {&lt;br /&gt;
		if (!diffBugAlert.list[word]) {&lt;br /&gt;
			diffBugAlert.list[word] = 1;&lt;br /&gt;
			alert(&#039;Bad word: &#039; + word + &#039;\n\nPlease report this bug.&#039;);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	diffBugAlert.list = {};&lt;br /&gt;
&lt;br /&gt;
	function makeDiffHashtable(src) {&lt;br /&gt;
		const ret = {};&lt;br /&gt;
		for (let i = 0; i &amp;lt; src.length; i++) {&lt;br /&gt;
			if (jsReservedProperties.test(src[i])) {&lt;br /&gt;
				src[i] += &#039;&amp;lt;!-- --&amp;gt;&#039;;&lt;br /&gt;
			}&lt;br /&gt;
			if (!ret[src[i]]) {&lt;br /&gt;
				ret[src[i]] = [];&lt;br /&gt;
			}&lt;br /&gt;
			try {&lt;br /&gt;
				ret[src[i]].push(i);&lt;br /&gt;
			} catch (err) {&lt;br /&gt;
				diffBugAlert(src[i]);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return ret;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function diff(o, n) {&lt;br /&gt;
		// pass 1: make hashtable ns with new rows as keys&lt;br /&gt;
		const ns = makeDiffHashtable(n);&lt;br /&gt;
&lt;br /&gt;
		// pass 2: make hashtable os with old rows as keys&lt;br /&gt;
		const os = makeDiffHashtable(o);&lt;br /&gt;
&lt;br /&gt;
		// pass 3: pair unique new rows and matching unique old rows&lt;br /&gt;
		let i;&lt;br /&gt;
		for (i in ns) {&lt;br /&gt;
			if (ns[i].length == 1 &amp;amp;&amp;amp; os[i] &amp;amp;&amp;amp; os[i].length == 1) {&lt;br /&gt;
				n[ns[i][0]] = { text: n[ns[i][0]], row: os[i][0], paired: true };&lt;br /&gt;
				o[os[i][0]] = { text: o[os[i][0]], row: ns[i][0], paired: true };&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// pass 4: pair matching rows immediately following paired rows (not necessarily unique)&lt;br /&gt;
		for (i = 0; i &amp;lt; n.length - 1; i++) {&lt;br /&gt;
			if (&lt;br /&gt;
				n[i].paired &amp;amp;&amp;amp;&lt;br /&gt;
				!n[i + 1].paired &amp;amp;&amp;amp;&lt;br /&gt;
				n[i].row + 1 &amp;lt; o.length &amp;amp;&amp;amp;&lt;br /&gt;
				!o[n[i].row + 1].paired &amp;amp;&amp;amp;&lt;br /&gt;
				n[i + 1] == o[n[i].row + 1]&lt;br /&gt;
			) {&lt;br /&gt;
				n[i + 1] = { text: n[i + 1], row: n[i].row + 1, paired: true };&lt;br /&gt;
				o[n[i].row + 1] = { text: o[n[i].row + 1], row: i + 1, paired: true };&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// pass 5: pair matching rows immediately preceding paired rows (not necessarily unique)&lt;br /&gt;
		for (i = n.length - 1; i &amp;gt; 0; i--) {&lt;br /&gt;
			if (&lt;br /&gt;
				n[i].paired &amp;amp;&amp;amp;&lt;br /&gt;
				!n[i - 1].paired &amp;amp;&amp;amp;&lt;br /&gt;
				n[i].row &amp;gt; 0 &amp;amp;&amp;amp;&lt;br /&gt;
				!o[n[i].row - 1].paired &amp;amp;&amp;amp;&lt;br /&gt;
				n[i - 1] == o[n[i].row - 1]&lt;br /&gt;
			) {&lt;br /&gt;
				n[i - 1] = { text: n[i - 1], row: n[i].row - 1, paired: true };&lt;br /&gt;
				o[n[i].row - 1] = { text: o[n[i].row - 1], row: i - 1, paired: true };&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		return { o: o, n: n };&lt;br /&gt;
	}&lt;br /&gt;
	// ENDFILE: diff.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: init.js&lt;br /&gt;
	function setSiteInfo() {&lt;br /&gt;
		if (window.popupLocalDebug) {&lt;br /&gt;
			pg.wiki.hostname = &#039;en.wikipedia.org&#039;;&lt;br /&gt;
		} else {&lt;br /&gt;
			pg.wiki.hostname = location.hostname; // use in preference to location.hostname for flexibility (?)&lt;br /&gt;
		}&lt;br /&gt;
		pg.wiki.wikimedia = /(wiki([pm]edia|source|books|news|quote|versity|species|voyage|data)|metawiki|wiktionary|mediawiki)[.]org/.test(pg.wiki.hostname);&lt;br /&gt;
		pg.wiki.wikia = /[.]wikia[.]com$/i.test(pg.wiki.hostname);&lt;br /&gt;
		pg.wiki.isLocal = /^localhost/.test(pg.wiki.hostname);&lt;br /&gt;
		pg.wiki.commons =&lt;br /&gt;
			pg.wiki.wikimedia &amp;amp;&amp;amp; pg.wiki.hostname != &#039;commons.wikimedia.org&#039; ?&lt;br /&gt;
				&#039;commons.wikimedia.org&#039; :&lt;br /&gt;
				null;&lt;br /&gt;
		pg.wiki.lang = mw.config.get(&#039;wgContentLanguage&#039;);&lt;br /&gt;
		const port = location.port ? &#039;:&#039; + location.port : &#039;&#039;;&lt;br /&gt;
		pg.wiki.sitebase = pg.wiki.hostname + port;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function setUserInfo() {&lt;br /&gt;
		const params = {&lt;br /&gt;
			action: &#039;query&#039;,&lt;br /&gt;
			list: &#039;users&#039;,&lt;br /&gt;
			ususers: mw.config.get(&#039;wgUserName&#039;),&lt;br /&gt;
			usprop: &#039;rights&#039;,&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		pg.user.canReview = false;&lt;br /&gt;
		if (getValueOf(&#039;popupReview&#039;)) {&lt;br /&gt;
			getMwApi()&lt;br /&gt;
				.get(params)&lt;br /&gt;
				.done((data) =&amp;gt; {&lt;br /&gt;
					const rights = data.query.users[0].rights;&lt;br /&gt;
					pg.user.canReview = rights.indexOf(&#039;review&#039;) !== -1; // TODO: Should it be a getValueOf(&#039;ReviewRight&#039;) ?&lt;br /&gt;
				});&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function fetchSpecialPageNames() {&lt;br /&gt;
		const params = {&lt;br /&gt;
			action: &#039;query&#039;,&lt;br /&gt;
			meta: &#039;siteinfo&#039;,&lt;br /&gt;
			siprop: &#039;specialpagealiases&#039;,&lt;br /&gt;
			formatversion: 2,&lt;br /&gt;
			// cache for an hour&lt;br /&gt;
			uselang: &#039;content&#039;,&lt;br /&gt;
			maxage: 3600,&lt;br /&gt;
		};&lt;br /&gt;
		return getMwApi()&lt;br /&gt;
			.get(params)&lt;br /&gt;
			.then((data) =&amp;gt; {&lt;br /&gt;
				pg.wiki.specialpagealiases = data.query.specialpagealiases;&lt;br /&gt;
			});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function setTitleBase() {&lt;br /&gt;
		const protocol = window.popupLocalDebug ? &#039;http:&#039; : location.protocol;&lt;br /&gt;
		pg.wiki.articlePath = mw.config.get(&#039;wgArticlePath&#039;).replace(/\/\$1/, &#039;&#039;); // as in http://some.thing.com/wiki/Article&lt;br /&gt;
		pg.wiki.botInterfacePath = mw.config.get(&#039;wgScript&#039;);&lt;br /&gt;
		pg.wiki.APIPath = mw.config.get(&#039;wgScriptPath&#039;) + &#039;/api.php&#039;;&lt;br /&gt;
		// default mediawiki setting is paths like http://some.thing.com/articlePath/index.php?title=foo&lt;br /&gt;
&lt;br /&gt;
		const titletail = pg.wiki.botInterfacePath + &#039;?title=&#039;;&lt;br /&gt;
		//var titletail2 = joinPath([pg.wiki.botInterfacePath, &#039;wiki.phtml?title=&#039;]);&lt;br /&gt;
&lt;br /&gt;
		// other sites may need to add code here to set titletail depending on how their urls work&lt;br /&gt;
&lt;br /&gt;
		pg.wiki.titlebase = protocol + &#039;//&#039; + pg.wiki.sitebase + titletail;&lt;br /&gt;
		//pg.wiki.titlebase2  = protocol + &#039;//&#039; + joinPath([pg.wiki.sitebase, titletail2]);&lt;br /&gt;
		pg.wiki.wikibase = protocol + &#039;//&#039; + pg.wiki.sitebase + pg.wiki.botInterfacePath;&lt;br /&gt;
		pg.wiki.apiwikibase = protocol + &#039;//&#039; + pg.wiki.sitebase + pg.wiki.APIPath;&lt;br /&gt;
		pg.wiki.articlebase = protocol + &#039;//&#039; + pg.wiki.sitebase + pg.wiki.articlePath;&lt;br /&gt;
		pg.wiki.commonsbase = protocol + &#039;//&#039; + pg.wiki.commons + pg.wiki.botInterfacePath;&lt;br /&gt;
		pg.wiki.apicommonsbase = protocol + &#039;//&#039; + pg.wiki.commons + pg.wiki.APIPath;&lt;br /&gt;
		pg.re.basenames = RegExp(&lt;br /&gt;
			&#039;^(&#039; +&lt;br /&gt;
				map(literalizeRegex, [&lt;br /&gt;
					pg.wiki.titlebase, //pg.wiki.titlebase2,&lt;br /&gt;
					pg.wiki.articlebase,&lt;br /&gt;
				]).join(&#039;|&#039;) +&lt;br /&gt;
				&#039;)&#039;&lt;br /&gt;
		);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	//////////////////////////////////////////////////&lt;br /&gt;
	// Global regexps&lt;br /&gt;
&lt;br /&gt;
	function setMainRegex() {&lt;br /&gt;
		const reStart = &#039;[^:]*://&#039;;&lt;br /&gt;
		let preTitles =&lt;br /&gt;
			// Take customizable wgScript into account (it isn&#039;t guaranteed to be index.php)&lt;br /&gt;
			&#039;(?:&#039; + literalizeRegex(mw.config.get(&#039;wgScript&#039;)) + &#039;|&#039; +&lt;br /&gt;
			// handle index.php (likely to work even if different from wgScript) and legacy wiki.phtml&lt;br /&gt;
			literalizeRegex(mw.config.get(&#039;wgScriptPath&#039;)) + &#039;/(?:index[.]php|wiki[.]phtml))&#039;;&lt;br /&gt;
		preTitles += &#039;[?]title=|&#039; + literalizeRegex(pg.wiki.articlePath + &#039;/&#039;);&lt;br /&gt;
		const reEnd = &#039;(&#039; + preTitles + &#039;)([^&amp;amp;?#]*)[^#]*(?:#(.+))?&#039;;&lt;br /&gt;
		pg.re.main = RegExp(reStart + literalizeRegex(pg.wiki.sitebase) + reEnd);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function buildSpecialPageGroup(specialPageObj) {&lt;br /&gt;
		const variants = [];&lt;br /&gt;
		variants.push(mw.util.escapeRegExp(specialPageObj.realname));&lt;br /&gt;
		variants.push(mw.util.escapeRegExp(encodeURI(specialPageObj.realname)));&lt;br /&gt;
		specialPageObj.aliases.forEach((alias) =&amp;gt; {&lt;br /&gt;
			variants.push(mw.util.escapeRegExp(alias));&lt;br /&gt;
			variants.push(mw.util.escapeRegExp(encodeURI(alias)));&lt;br /&gt;
		});&lt;br /&gt;
		return variants.join(&#039;|&#039;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function setRegexps() {&lt;br /&gt;
		setMainRegex();&lt;br /&gt;
		const sp = nsRe(pg.nsSpecialId);&lt;br /&gt;
		pg.re.urlNoPopup = RegExp(&#039;((title=|/)&#039; + sp + &#039;(?:%3A|:)|section=[0-9]|^#$)&#039;);&lt;br /&gt;
&lt;br /&gt;
		pg.wiki.specialpagealiases.forEach((specialpage) =&amp;gt; {&lt;br /&gt;
			if (specialpage.realname === &#039;Contributions&#039;) {&lt;br /&gt;
				pg.re.contribs = RegExp(&lt;br /&gt;
					&#039;(title=|/)&#039; +&lt;br /&gt;
						sp +&lt;br /&gt;
						&#039;(?:%3A|:)(?:&#039; +&lt;br /&gt;
						buildSpecialPageGroup(specialpage) +&lt;br /&gt;
						&#039;)&#039; +&lt;br /&gt;
						&#039;(&amp;amp;target=|/|/&#039; +&lt;br /&gt;
						nsRe(pg.nsUserId) +&lt;br /&gt;
						&#039;:)(.*)&#039;,&lt;br /&gt;
					&#039;i&#039;&lt;br /&gt;
				);&lt;br /&gt;
			} else if (specialpage.realname === &#039;Diff&#039;) {&lt;br /&gt;
				pg.re.specialdiff = RegExp(&lt;br /&gt;
					&#039;/&#039; + sp + &#039;(?:%3A|:)(?:&#039; + buildSpecialPageGroup(specialpage) + &#039;)/([^?#]*)&#039;,&lt;br /&gt;
					&#039;i&#039;&lt;br /&gt;
				);&lt;br /&gt;
			} else if (specialpage.realname === &#039;Emailuser&#039;) {&lt;br /&gt;
				pg.re.email = RegExp(&lt;br /&gt;
					&#039;(title=|/)&#039; +&lt;br /&gt;
						sp +&lt;br /&gt;
						&#039;(?:%3A|:)(?:&#039; +&lt;br /&gt;
						buildSpecialPageGroup(specialpage) +&lt;br /&gt;
						&#039;)&#039; +&lt;br /&gt;
						&#039;(&amp;amp;target=|/|/(?:&#039; +&lt;br /&gt;
						nsRe(pg.nsUserId) +&lt;br /&gt;
						&#039;:)?)(.*)&#039;,&lt;br /&gt;
					&#039;i&#039;&lt;br /&gt;
				);&lt;br /&gt;
			} else if (specialpage.realname === &#039;Whatlinkshere&#039;) {&lt;br /&gt;
				pg.re.backlinks = RegExp(&lt;br /&gt;
					&#039;(title=|/)&#039; +&lt;br /&gt;
						sp +&lt;br /&gt;
						&#039;(?:%3A|:)(?:&#039; +&lt;br /&gt;
						buildSpecialPageGroup(specialpage) +&lt;br /&gt;
						&#039;)&#039; +&lt;br /&gt;
						&#039;(&amp;amp;target=|/)([^&amp;amp;]*)&#039;,&lt;br /&gt;
					&#039;i&#039;&lt;br /&gt;
				);&lt;br /&gt;
			}&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		const im = nsReImage();&lt;br /&gt;
		// note: tries to get images in infobox templates too, e.g. movie pages, album pages etc&lt;br /&gt;
		//					  (^|\[\[)image: *([^|\]]*[^|\] ]) *&lt;br /&gt;
		//					  (^|\[\[)image: *([^|\]]*[^|\] ])([^0-9\]]*([0-9]+) *px)?&lt;br /&gt;
		//														$4 = 120 as in 120px&lt;br /&gt;
		pg.re.image = RegExp(&lt;br /&gt;
			&#039;(^|\\[\\[)&#039; +&lt;br /&gt;
				im +&lt;br /&gt;
				&#039;: *([^|\\]]*[^|\\] ])&#039; +&lt;br /&gt;
				&#039;([^0-9\\]]*([0-9]+) *px)?|(?:\\n *[|]?|[|]) *&#039; +&lt;br /&gt;
				&#039;(&#039; +&lt;br /&gt;
				getValueOf(&#039;popupImageVarsRegexp&#039;) +&lt;br /&gt;
				&#039;)&#039; +&lt;br /&gt;
				&#039; *= *(?:\\[\\[ *)?(?:&#039; +&lt;br /&gt;
				im +&lt;br /&gt;
				&#039;:)?&#039; +&lt;br /&gt;
				&#039;([^|]*?)(?:\\]\\])? *[|]? *\\n&#039;,&lt;br /&gt;
			&#039;img&#039;&lt;br /&gt;
		);&lt;br /&gt;
		pg.re.imageBracketCount = 6;&lt;br /&gt;
&lt;br /&gt;
		pg.re.category = RegExp(&#039;\\[\\[&#039; + nsRe(pg.nsCategoryId) + &#039;: *([^|\\]]*[^|\\] ]) *&#039;, &#039;i&#039;);&lt;br /&gt;
		pg.re.categoryBracketCount = 1;&lt;br /&gt;
&lt;br /&gt;
		pg.re.ipUser = RegExp(&lt;br /&gt;
			&#039;^&#039; +&lt;br /&gt;
				// IPv6&lt;br /&gt;
				&#039;(?::(?::|(?::[0-9A-Fa-f]{1,4}){1,7})|[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4}){0,6}::|[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4}){7})&#039; +&lt;br /&gt;
				// IPv4&lt;br /&gt;
				&#039;|(((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}&#039; +&lt;br /&gt;
				&#039;(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9]))$&#039;&lt;br /&gt;
		);&lt;br /&gt;
&lt;br /&gt;
		pg.re.stub = RegExp(getValueOf(&#039;popupStubRegexp&#039;), &#039;im&#039;);&lt;br /&gt;
		pg.re.disambig = RegExp(getValueOf(&#039;popupDabRegexp&#039;), &#039;im&#039;);&lt;br /&gt;
&lt;br /&gt;
		// FIXME replace with general parameter parsing function, this is daft&lt;br /&gt;
		pg.re.oldid = /[?&amp;amp;]oldid=([^&amp;amp;]*)/;&lt;br /&gt;
		pg.re.diff = /[?&amp;amp;]diff=([^&amp;amp;]*)/;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	//////////////////////////////////////////////////&lt;br /&gt;
	// miscellany&lt;br /&gt;
&lt;br /&gt;
	function setupCache() {&lt;br /&gt;
		// page caching&lt;br /&gt;
		pg.cache.pages = [];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function setMisc() {&lt;br /&gt;
		pg.current.link = null;&lt;br /&gt;
		pg.current.links = [];&lt;br /&gt;
		pg.current.linksHash = {};&lt;br /&gt;
&lt;br /&gt;
		setupCache();&lt;br /&gt;
&lt;br /&gt;
		pg.timer.checkPopupPosition = null;&lt;br /&gt;
		pg.counter.loop = 0;&lt;br /&gt;
&lt;br /&gt;
		// ids change with each popup: popupImage0, popupImage1 etc&lt;br /&gt;
		pg.idNumber = 0;&lt;br /&gt;
&lt;br /&gt;
		// for myDecodeURI&lt;br /&gt;
		pg.misc.decodeExtras = [&lt;br /&gt;
			{ from: &#039;%2C&#039;, to: &#039;,&#039; },&lt;br /&gt;
			{ from: &#039;_&#039;, to: &#039; &#039; },&lt;br /&gt;
			{ from: &#039;%24&#039;, to: &#039;$&#039; },&lt;br /&gt;
			{ from: &#039;%26&#039;, to: &#039;&amp;amp;&#039; }, // no ,&lt;br /&gt;
		];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function getMwApi() {&lt;br /&gt;
		if (!pg.api.client) {&lt;br /&gt;
			pg.api.userAgent = &#039;Navigation popups/1.0 (&#039; + mw.config.get(&#039;wgServerName&#039;) + &#039;)&#039;;&lt;br /&gt;
			pg.api.client = new mw.Api({&lt;br /&gt;
				ajax: {&lt;br /&gt;
					headers: {&lt;br /&gt;
						&#039;Api-User-Agent&#039;: pg.api.userAgent,&lt;br /&gt;
					},&lt;br /&gt;
				},&lt;br /&gt;
			});&lt;br /&gt;
		}&lt;br /&gt;
		return pg.api.client;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// We need a callback since this might end up asynchronous because of&lt;br /&gt;
	// the mw.loader.using() call.&lt;br /&gt;
	function setupPopups(callback) {&lt;br /&gt;
		if (setupPopups.completed) {&lt;br /&gt;
			if (typeof callback === &#039;function&#039;) {&lt;br /&gt;
				callback();&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		// These dependencies should alse be enforced from the gadget,&lt;br /&gt;
		// but not everyone loads this as a gadget, so double check&lt;br /&gt;
		mw.loader&lt;br /&gt;
			.using([&lt;br /&gt;
				&#039;mediawiki.util&#039;,&lt;br /&gt;
				&#039;mediawiki.api&#039;,&lt;br /&gt;
				&#039;mediawiki.user&#039;,&lt;br /&gt;
				&#039;user.options&#039;,&lt;br /&gt;
				&#039;mediawiki.jqueryMsg&#039;,&lt;br /&gt;
			])&lt;br /&gt;
			.then(fetchSpecialPageNames)&lt;br /&gt;
			.then(() =&amp;gt; {&lt;br /&gt;
				// NB translatable strings should be set up first (strings.js)&lt;br /&gt;
				// basics&lt;br /&gt;
				setupDebugging();&lt;br /&gt;
				setSiteInfo();&lt;br /&gt;
				setTitleBase();&lt;br /&gt;
				setOptions(); // see options.js&lt;br /&gt;
				setUserInfo();&lt;br /&gt;
&lt;br /&gt;
				// namespaces etc&lt;br /&gt;
				setNamespaces();&lt;br /&gt;
				setInterwiki();&lt;br /&gt;
&lt;br /&gt;
				// regexps&lt;br /&gt;
				setRegexps();&lt;br /&gt;
				setRedirs();&lt;br /&gt;
&lt;br /&gt;
				// other stuff&lt;br /&gt;
				setMisc();&lt;br /&gt;
				setupLivePreview();&lt;br /&gt;
&lt;br /&gt;
				// main deal here&lt;br /&gt;
				setupTooltips();&lt;br /&gt;
				log(&#039;In setupPopups(), just called setupTooltips()&#039;);&lt;br /&gt;
				Navpopup.tracker.enable();&lt;br /&gt;
&lt;br /&gt;
				setupPopups.completed = true;&lt;br /&gt;
				if (typeof callback === &#039;function&#039;) {&lt;br /&gt;
					callback();&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
	}&lt;br /&gt;
	// ENDFILE: init.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: navlinks.js&lt;br /&gt;
	//////////////////////////////////////////////////&lt;br /&gt;
	// navlinks... let the fun begin&lt;br /&gt;
	//&lt;br /&gt;
&lt;br /&gt;
	function defaultNavlinkSpec() {&lt;br /&gt;
		let str = &#039;&#039;;&lt;br /&gt;
		str += &#039;&amp;lt;b&amp;gt;&amp;lt;&amp;lt;mainlink|shortcut= &amp;gt;&amp;gt;&amp;lt;/b&amp;gt;&#039;;&lt;br /&gt;
		if (getValueOf(&#039;popupLastEditLink&#039;)) {&lt;br /&gt;
			str +=&lt;br /&gt;
				&#039;*&amp;lt;&amp;lt;lastEdit|shortcut=/&amp;gt;&amp;gt;|&amp;lt;&amp;lt;lastContrib&amp;gt;&amp;gt;|&amp;lt;&amp;lt;sinceMe&amp;gt;&amp;gt;if(oldid){|&amp;lt;&amp;lt;oldEdit&amp;gt;&amp;gt;|&amp;lt;&amp;lt;diffCur&amp;gt;&amp;gt;}&#039;;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// user links&lt;br /&gt;
		// contribs - log - count - email - block&lt;br /&gt;
		// count only if applicable; block only if popupAdminLinks&lt;br /&gt;
		str += &#039;if(user){&amp;lt;br&amp;gt;&amp;lt;&amp;lt;contribs|shortcut=c&amp;gt;&amp;gt;*&amp;lt;&amp;lt;userlog|shortcut=L|log&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
		str += &#039;if(ipuser){*&amp;lt;&amp;lt;arin&amp;gt;&amp;gt;}if(wikimedia){*&amp;lt;&amp;lt;count|shortcut=#&amp;gt;&amp;gt;}&#039;;&lt;br /&gt;
		str +=&lt;br /&gt;
			&#039;if(ipuser){}else{*&amp;lt;&amp;lt;email|shortcut=E&amp;gt;&amp;gt;}if(admin){*&amp;lt;&amp;lt;block|shortcut=b&amp;gt;&amp;gt;|&amp;lt;&amp;lt;blocklog|log&amp;gt;&amp;gt;}}&#039;;&lt;br /&gt;
&lt;br /&gt;
		// editing links&lt;br /&gt;
		// talkpage   -&amp;gt; edit|new - history - un|watch - article|edit&lt;br /&gt;
		// other page -&amp;gt; edit - history - un|watch - talk|edit|new&lt;br /&gt;
		const editstr = &#039;&amp;lt;&amp;lt;edit|shortcut=e&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
		const editOldidStr =&lt;br /&gt;
			&#039;if(oldid){&amp;lt;&amp;lt;editOld|shortcut=e&amp;gt;&amp;gt;|&amp;lt;&amp;lt;revert|shortcut=v|rv&amp;gt;&amp;gt;|&amp;lt;&amp;lt;edit|cur&amp;gt;&amp;gt;}else{&#039; +&lt;br /&gt;
			editstr +&lt;br /&gt;
			&#039;}&#039;;&lt;br /&gt;
		const historystr = &#039;&amp;lt;&amp;lt;history|shortcut=h&amp;gt;&amp;gt;|&amp;lt;&amp;lt;editors|shortcut=E|&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
		const watchstr = &#039;&amp;lt;&amp;lt;unwatch|unwatchShort&amp;gt;&amp;gt;|&amp;lt;&amp;lt;watch|shortcut=w|watchThingy&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
		str +=&lt;br /&gt;
			&#039;&amp;lt;br&amp;gt;if(talk){&#039; +&lt;br /&gt;
			editOldidStr +&lt;br /&gt;
			&#039;|&amp;lt;&amp;lt;new|shortcut=+&amp;gt;&amp;gt;&#039; +&lt;br /&gt;
			&#039;*&#039; +&lt;br /&gt;
			historystr +&lt;br /&gt;
			&#039;*&#039; +&lt;br /&gt;
			watchstr +&lt;br /&gt;
			&#039;*&#039; +&lt;br /&gt;
			&#039;&amp;lt;b&amp;gt;&amp;lt;&amp;lt;article|shortcut=a&amp;gt;&amp;gt;&amp;lt;/b&amp;gt;|&amp;lt;&amp;lt;editArticle|edit&amp;gt;&amp;gt;&#039; +&lt;br /&gt;
			&#039;}else{&#039; + // not a talk page&lt;br /&gt;
			editOldidStr +&lt;br /&gt;
			&#039;*&#039; +&lt;br /&gt;
			historystr +&lt;br /&gt;
			&#039;*&#039; +&lt;br /&gt;
			watchstr +&lt;br /&gt;
			&#039;*&#039; +&lt;br /&gt;
			&#039;&amp;lt;b&amp;gt;&amp;lt;&amp;lt;talk|shortcut=t&amp;gt;&amp;gt;&amp;lt;/b&amp;gt;|&amp;lt;&amp;lt;editTalk|edit&amp;gt;&amp;gt;|&amp;lt;&amp;lt;newTalk|shortcut=+|new&amp;gt;&amp;gt;}&#039;;&lt;br /&gt;
&lt;br /&gt;
		// misc links&lt;br /&gt;
		str += &#039;&amp;lt;br&amp;gt;&amp;lt;&amp;lt;whatLinksHere|shortcut=l&amp;gt;&amp;gt;*&amp;lt;&amp;lt;relatedChanges|shortcut=r&amp;gt;&amp;gt;*&amp;lt;&amp;lt;move|shortcut=m&amp;gt;&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
		// admin links&lt;br /&gt;
		str +=&lt;br /&gt;
			&#039;if(admin){&amp;lt;br&amp;gt;&amp;lt;&amp;lt;unprotect|unprotectShort&amp;gt;&amp;gt;|&amp;lt;&amp;lt;protect|shortcut=p&amp;gt;&amp;gt;|&amp;lt;&amp;lt;protectlog|log&amp;gt;&amp;gt;*&#039; +&lt;br /&gt;
			&#039;&amp;lt;&amp;lt;undelete|undeleteShort&amp;gt;&amp;gt;|&amp;lt;&amp;lt;delete|shortcut=d&amp;gt;&amp;gt;|&amp;lt;&amp;lt;deletelog|log&amp;gt;&amp;gt;}&#039;;&lt;br /&gt;
		return str;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function navLinksHTML(article, hint, params) {&lt;br /&gt;
		//oldid, rcid) {&lt;br /&gt;
		const str = &#039;&amp;lt;span class=&amp;quot;popupNavLinks&amp;quot;&amp;gt;&#039; + defaultNavlinkSpec() + &#039;&amp;lt;/span&amp;gt;&#039;;&lt;br /&gt;
		// BAM&lt;br /&gt;
		return navlinkStringToHTML(str, article, params);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function expandConditionalNavlinkString(s, article, z, recursionCount) {&lt;br /&gt;
		const oldid = z.oldid,&lt;br /&gt;
			rcid = z.rcid,&lt;br /&gt;
			diff = z.diff;&lt;br /&gt;
		// nested conditionals (up to 10 deep) are ok, hopefully! (work from the inside out)&lt;br /&gt;
		if (typeof recursionCount != typeof 0) {&lt;br /&gt;
			recursionCount = 0;&lt;br /&gt;
		}&lt;br /&gt;
		const conditionalSplitRegex = RegExp(&lt;br /&gt;
			//(1	 if	\\(	(2	2)	\\)	  {(3	3)}  (4   else	  {(5	 5)}  4)1)&lt;br /&gt;
			&#039;(;?\\s*if\\s*\\(\\s*([\\w]*)\\s*\\)\\s*\\{([^{}]*)\\}(\\s*else\\s*\\{([^{}]*?)\\}|))&#039;,&lt;br /&gt;
			&#039;i&#039;&lt;br /&gt;
		);&lt;br /&gt;
		const splitted = s.parenSplit(conditionalSplitRegex);&lt;br /&gt;
		// $1: whole conditional&lt;br /&gt;
		// $2: test condition&lt;br /&gt;
		// $3: true expansion&lt;br /&gt;
		// $4: else clause (possibly empty)&lt;br /&gt;
		// $5: false expansion (possibly null)&lt;br /&gt;
		const numParens = 5;&lt;br /&gt;
		let ret = splitted[0];&lt;br /&gt;
		for (let i = 1; i &amp;lt; splitted.length; i = i + numParens + 1) {&lt;br /&gt;
			const testString = splitted[i + 2 - 1];&lt;br /&gt;
			const trueString = splitted[i + 3 - 1];&lt;br /&gt;
			let falseString = splitted[i + 5 - 1];&lt;br /&gt;
			if (typeof falseString == &#039;undefined&#039; || !falseString) {&lt;br /&gt;
				falseString = &#039;&#039;;&lt;br /&gt;
			}&lt;br /&gt;
			let testResult = null;&lt;br /&gt;
&lt;br /&gt;
			switch (testString) {&lt;br /&gt;
				case &#039;user&#039;:&lt;br /&gt;
					testResult = !!article.userName();&lt;br /&gt;
					break;&lt;br /&gt;
				case &#039;talk&#039;:&lt;br /&gt;
					testResult = !article.talkPage(); // talkPage converts _articles_ to talkPages&lt;br /&gt;
					break;&lt;br /&gt;
				case &#039;admin&#039;:&lt;br /&gt;
					testResult = !!getValueOf(&#039;popupAdminLinks&#039;);&lt;br /&gt;
					break;&lt;br /&gt;
				case &#039;oldid&#039;:&lt;br /&gt;
					testResult = !!(typeof oldid != &#039;undefined&#039; &amp;amp;&amp;amp; oldid);&lt;br /&gt;
					break;&lt;br /&gt;
				case &#039;rcid&#039;:&lt;br /&gt;
					testResult = !!(typeof rcid != &#039;undefined&#039; &amp;amp;&amp;amp; rcid);&lt;br /&gt;
					break;&lt;br /&gt;
				case &#039;ipuser&#039;:&lt;br /&gt;
					testResult = !!article.isIpUser();&lt;br /&gt;
					break;&lt;br /&gt;
				case &#039;mainspace_en&#039;:&lt;br /&gt;
					testResult = isInMainNamespace(article) &amp;amp;&amp;amp; pg.wiki.hostname == &#039;en.wikipedia.org&#039;;&lt;br /&gt;
					break;&lt;br /&gt;
				case &#039;wikimedia&#039;:&lt;br /&gt;
					testResult = !!pg.wiki.wikimedia;&lt;br /&gt;
					break;&lt;br /&gt;
				case &#039;diff&#039;:&lt;br /&gt;
					testResult = !!(typeof diff != &#039;undefined&#039; &amp;amp;&amp;amp; diff);&lt;br /&gt;
					break;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			switch (testResult) {&lt;br /&gt;
				case null:&lt;br /&gt;
					ret += splitted[i];&lt;br /&gt;
					break;&lt;br /&gt;
				case true:&lt;br /&gt;
					ret += trueString;&lt;br /&gt;
					break;&lt;br /&gt;
				case false:&lt;br /&gt;
					ret += falseString;&lt;br /&gt;
					break;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			// append non-conditional string&lt;br /&gt;
			ret += splitted[i + numParens];&lt;br /&gt;
		}&lt;br /&gt;
		if (conditionalSplitRegex.test(ret) &amp;amp;&amp;amp; recursionCount &amp;lt; 10) {&lt;br /&gt;
			return expandConditionalNavlinkString(ret, article, z, recursionCount + 1);&lt;br /&gt;
		}&lt;br /&gt;
		return ret;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function navlinkStringToArray(s, article, params) {&lt;br /&gt;
		s = expandConditionalNavlinkString(s, article, params);&lt;br /&gt;
		const splitted = s.parenSplit(/&amp;lt;&amp;lt;(.*?)&amp;gt;&amp;gt;/);&lt;br /&gt;
		const ret = [];&lt;br /&gt;
		for (let i = 0; i &amp;lt; splitted.length; ++i) {&lt;br /&gt;
			if (i % 2) {&lt;br /&gt;
				// i odd, so s is a tag&lt;br /&gt;
				const t = new navlinkTag();&lt;br /&gt;
				const ss = splitted[i].split(&#039;|&#039;);&lt;br /&gt;
				t.id = ss[0];&lt;br /&gt;
				for (let j = 1; j &amp;lt; ss.length; ++j) {&lt;br /&gt;
					const sss = ss[j].split(&#039;=&#039;);&lt;br /&gt;
					if (sss.length &amp;gt; 1) {&lt;br /&gt;
						t[sss[0]] = sss[1];&lt;br /&gt;
					} else {&lt;br /&gt;
						// no assignment (no &amp;quot;=&amp;quot;), so treat this as a title (overwriting the last one)&lt;br /&gt;
						t.text = popupString(sss[0]);&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				t.article = article;&lt;br /&gt;
				const oldid = params.oldid,&lt;br /&gt;
					rcid = params.rcid,&lt;br /&gt;
					diff = params.diff;&lt;br /&gt;
				if (typeof oldid !== &#039;undefined&#039; &amp;amp;&amp;amp; oldid !== null) {&lt;br /&gt;
					t.oldid = oldid;&lt;br /&gt;
				}&lt;br /&gt;
				if (typeof rcid !== &#039;undefined&#039; &amp;amp;&amp;amp; rcid !== null) {&lt;br /&gt;
					t.rcid = rcid;&lt;br /&gt;
				}&lt;br /&gt;
				if (typeof diff !== &#039;undefined&#039; &amp;amp;&amp;amp; diff !== null) {&lt;br /&gt;
					t.diff = diff;&lt;br /&gt;
				}&lt;br /&gt;
				if (!t.text &amp;amp;&amp;amp; t.id !== &#039;mainlink&#039;) {&lt;br /&gt;
					t.text = popupString(t.id);&lt;br /&gt;
				}&lt;br /&gt;
				ret.push(t);&lt;br /&gt;
			} else {&lt;br /&gt;
				// plain HTML&lt;br /&gt;
				ret.push(splitted[i]);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return ret;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function navlinkSubstituteHTML(s) {&lt;br /&gt;
		return s&lt;br /&gt;
			.split(&#039;*&#039;)&lt;br /&gt;
			.join(getValueOf(&#039;popupNavLinkSeparator&#039;))&lt;br /&gt;
			.split(&#039;&amp;lt;menurow&amp;gt;&#039;)&lt;br /&gt;
			.join(&#039;&amp;lt;li class=&amp;quot;popup_menu_row&amp;quot;&amp;gt;&#039;)&lt;br /&gt;
			.split(&#039;&amp;lt;/menurow&amp;gt;&#039;)&lt;br /&gt;
			.join(&#039;&amp;lt;/li&amp;gt;&#039;)&lt;br /&gt;
			.split(&#039;&amp;lt;menu&amp;gt;&#039;)&lt;br /&gt;
			.join(&#039;&amp;lt;ul class=&amp;quot;popup_menu&amp;quot;&amp;gt;&#039;)&lt;br /&gt;
			.split(&#039;&amp;lt;/menu&amp;gt;&#039;)&lt;br /&gt;
			.join(&#039;&amp;lt;/ul&amp;gt;&#039;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function navlinkDepth(magic, s) {&lt;br /&gt;
		return s.split(&#039;&amp;lt;&#039; + magic + &#039;&amp;gt;&#039;).length - s.split(&#039;&amp;lt;/&#039; + magic + &#039;&amp;gt;&#039;).length;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// navlinkString: * becomes the separator&lt;br /&gt;
	//				&amp;lt;&amp;lt;foo|bar=baz|fubar&amp;gt;&amp;gt; becomes a foo-link with attribute bar=&#039;baz&#039;&lt;br /&gt;
	//									  and visible text &#039;fubar&#039;&lt;br /&gt;
	//				if(test){...} and if(test){...}else{...} work too (nested ok)&lt;br /&gt;
&lt;br /&gt;
	function navlinkStringToHTML(s, article, params) {&lt;br /&gt;
		//limitAlert(navlinkStringToHTML, 5, &#039;navlinkStringToHTML\n&#039; + article + &#039;\n&#039; + (typeof article));&lt;br /&gt;
		const p = navlinkStringToArray(s, article, params);&lt;br /&gt;
		let html = &#039;&#039;;&lt;br /&gt;
		let menudepth = 0; // nested menus not currently allowed, but doesn&#039;t do any harm to code for it&lt;br /&gt;
		let menurowdepth = 0;&lt;br /&gt;
		for (let i = 0; i &amp;lt; p.length; ++i) {&lt;br /&gt;
			if (typeof p[i] == typeof &#039;&#039;) {&lt;br /&gt;
				html += navlinkSubstituteHTML(p[i]);&lt;br /&gt;
				menudepth += navlinkDepth(&#039;menu&#039;, p[i]);&lt;br /&gt;
				menurowdepth += navlinkDepth(&#039;menurow&#039;, p[i]);&lt;br /&gt;
				//			if (menudepth === 0) {&lt;br /&gt;
				//				tagType=&#039;span&#039;;&lt;br /&gt;
				//			} else if (menurowdepth === 0) {&lt;br /&gt;
				//				tagType=&#039;li&#039;;&lt;br /&gt;
				//			} else {&lt;br /&gt;
				//				tagType = null;&lt;br /&gt;
				//			}&lt;br /&gt;
			} else if (typeof p[i].type != &#039;undefined&#039; &amp;amp;&amp;amp; p[i].type == &#039;navlinkTag&#039;) {&lt;br /&gt;
				if (menudepth &amp;gt; 0 &amp;amp;&amp;amp; menurowdepth === 0) {&lt;br /&gt;
					html += &#039;&amp;lt;li class=&amp;quot;popup_menu_item&amp;quot;&amp;gt;&#039; + p[i].html() + &#039;&amp;lt;/li&amp;gt;&#039;;&lt;br /&gt;
				} else {&lt;br /&gt;
					html += p[i].html();&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return html;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function navlinkTag() {&lt;br /&gt;
		this.type = &#039;navlinkTag&#039;;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	navlinkTag.prototype.html = function () {&lt;br /&gt;
		this.getNewWin();&lt;br /&gt;
		this.getPrintFunction();&lt;br /&gt;
		let html = &#039;&#039;;&lt;br /&gt;
		let opening, closing;&lt;br /&gt;
		const tagType = &#039;span&#039;;&lt;br /&gt;
		if (!tagType) {&lt;br /&gt;
			opening = &#039;&#039;;&lt;br /&gt;
			closing = &#039;&#039;;&lt;br /&gt;
		} else {&lt;br /&gt;
			opening = &#039;&amp;lt;&#039; + tagType + &#039; class=&amp;quot;popup_&#039; + this.id + &#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
			closing = &#039;&amp;lt;/&#039; + tagType + &#039;&amp;gt;&#039;;&lt;br /&gt;
		}&lt;br /&gt;
		if (typeof this.print != &#039;function&#039;) {&lt;br /&gt;
			errlog(&#039;Oh dear - invalid print function for a navlinkTag, id=&#039; + this.id);&lt;br /&gt;
		} else {&lt;br /&gt;
			html = this.print(this);&lt;br /&gt;
			if (typeof html != typeof &#039;&#039;) {&lt;br /&gt;
				html = &#039;&#039;;&lt;br /&gt;
			} else if (typeof this.shortcut != &#039;undefined&#039;) {&lt;br /&gt;
				html = addPopupShortcut(html, this.shortcut);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return opening + html + closing;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	navlinkTag.prototype.getNewWin = function () {&lt;br /&gt;
		getValueOf(&#039;popupLinksNewWindow&#039;);&lt;br /&gt;
		if (typeof pg.option.popupLinksNewWindow[this.id] === &#039;undefined&#039;) {&lt;br /&gt;
			this.newWin = null;&lt;br /&gt;
		}&lt;br /&gt;
		this.newWin = pg.option.popupLinksNewWindow[this.id];&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	navlinkTag.prototype.getPrintFunction = function () {&lt;br /&gt;
		//think about this some more&lt;br /&gt;
		// this.id and this.article should already be defined&lt;br /&gt;
		if (typeof this.id != typeof &#039;&#039; || typeof this.article != typeof {}) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		this.noPopup = 1;&lt;br /&gt;
		switch (this.id) {&lt;br /&gt;
			case &#039;contribs&#039;:&lt;br /&gt;
			case &#039;history&#039;:&lt;br /&gt;
			case &#039;whatLinksHere&#039;:&lt;br /&gt;
			case &#039;userPage&#039;:&lt;br /&gt;
			case &#039;monobook&#039;:&lt;br /&gt;
			case &#039;userTalk&#039;:&lt;br /&gt;
			case &#039;talk&#039;:&lt;br /&gt;
			case &#039;article&#039;:&lt;br /&gt;
			case &#039;lastEdit&#039;:&lt;br /&gt;
				this.noPopup = null;&lt;br /&gt;
		}&lt;br /&gt;
		switch (this.id) {&lt;br /&gt;
			case &#039;email&#039;:&lt;br /&gt;
			case &#039;contribs&#039;:&lt;br /&gt;
			case &#039;block&#039;:&lt;br /&gt;
			case &#039;unblock&#039;:&lt;br /&gt;
			case &#039;userlog&#039;:&lt;br /&gt;
			case &#039;userSpace&#039;:&lt;br /&gt;
			case &#039;deletedContribs&#039;:&lt;br /&gt;
				this.article = this.article.userName();&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		switch (this.id) {&lt;br /&gt;
			case &#039;userTalk&#039;:&lt;br /&gt;
			case &#039;newUserTalk&#039;:&lt;br /&gt;
			case &#039;editUserTalk&#039;:&lt;br /&gt;
			case &#039;userPage&#039;:&lt;br /&gt;
			case &#039;monobook&#039;:&lt;br /&gt;
			case &#039;editMonobook&#039;:&lt;br /&gt;
			case &#039;blocklog&#039;:&lt;br /&gt;
				this.article = this.article.userName(true);&lt;br /&gt;
			/* fall through */&lt;br /&gt;
			case &#039;pagelog&#039;:&lt;br /&gt;
			case &#039;deletelog&#039;:&lt;br /&gt;
			case &#039;protectlog&#039;:&lt;br /&gt;
				delete this.oldid;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (this.id == &#039;editMonobook&#039; || this.id == &#039;monobook&#039;) {&lt;br /&gt;
			this.article.append(&#039;/monobook.js&#039;);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (this.id != &#039;mainlink&#039;) {&lt;br /&gt;
			// FIXME anchor handling should be done differently with Title object&lt;br /&gt;
			this.article = this.article.removeAnchor();&lt;br /&gt;
			// if (typeof this.text==&#039;undefined&#039;) this.text=popupString(this.id);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		switch (this.id) {&lt;br /&gt;
			case &#039;undelete&#039;:&lt;br /&gt;
				this.print = specialLink;&lt;br /&gt;
				this.specialpage = &#039;Undelete&#039;;&lt;br /&gt;
				this.sep = &#039;/&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;whatLinksHere&#039;:&lt;br /&gt;
				this.print = specialLink;&lt;br /&gt;
				this.specialpage = &#039;Whatlinkshere&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;relatedChanges&#039;:&lt;br /&gt;
				this.print = specialLink;&lt;br /&gt;
				this.specialpage = &#039;Recentchangeslinked&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;move&#039;:&lt;br /&gt;
				this.print = specialLink;&lt;br /&gt;
				this.specialpage = &#039;Movepage&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;contribs&#039;:&lt;br /&gt;
				this.print = specialLink;&lt;br /&gt;
				this.specialpage = &#039;Contributions&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;deletedContribs&#039;:&lt;br /&gt;
				this.print = specialLink;&lt;br /&gt;
				this.specialpage = &#039;Deletedcontributions&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;email&#039;:&lt;br /&gt;
				this.print = specialLink;&lt;br /&gt;
				this.specialpage = &#039;EmailUser&#039;;&lt;br /&gt;
				this.sep = &#039;/&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;block&#039;:&lt;br /&gt;
				this.print = specialLink;&lt;br /&gt;
				this.specialpage = &#039;Blockip&#039;;&lt;br /&gt;
				this.sep = &#039;&amp;amp;ip=&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;unblock&#039;:&lt;br /&gt;
				this.print = specialLink;&lt;br /&gt;
				this.specialpage = &#039;Ipblocklist&#039;;&lt;br /&gt;
				this.sep = &#039;&amp;amp;action=unblock&amp;amp;ip=&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;userlog&#039;:&lt;br /&gt;
				this.print = specialLink;&lt;br /&gt;
				this.specialpage = &#039;Log&#039;;&lt;br /&gt;
				this.sep = &#039;&amp;amp;user=&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;blocklog&#039;:&lt;br /&gt;
				this.print = specialLink;&lt;br /&gt;
				this.specialpage = &#039;Log&#039;;&lt;br /&gt;
				this.sep = &#039;&amp;amp;type=block&amp;amp;page=&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;pagelog&#039;:&lt;br /&gt;
				this.print = specialLink;&lt;br /&gt;
				this.specialpage = &#039;Log&#039;;&lt;br /&gt;
				this.sep = &#039;&amp;amp;page=&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;protectlog&#039;:&lt;br /&gt;
				this.print = specialLink;&lt;br /&gt;
				this.specialpage = &#039;Log&#039;;&lt;br /&gt;
				this.sep = &#039;&amp;amp;type=protect&amp;amp;page=&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;deletelog&#039;:&lt;br /&gt;
				this.print = specialLink;&lt;br /&gt;
				this.specialpage = &#039;Log&#039;;&lt;br /&gt;
				this.sep = &#039;&amp;amp;type=delete&amp;amp;page=&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;userSpace&#039;:&lt;br /&gt;
				this.print = specialLink;&lt;br /&gt;
				this.specialpage = &#039;PrefixIndex&#039;;&lt;br /&gt;
				this.sep = &#039;&amp;amp;namespace=2&amp;amp;prefix=&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;search&#039;:&lt;br /&gt;
				this.print = specialLink;&lt;br /&gt;
				this.specialpage = &#039;Search&#039;;&lt;br /&gt;
				this.sep = &#039;&amp;amp;fulltext=Search&amp;amp;search=&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;thank&#039;:&lt;br /&gt;
				this.print = specialLink;&lt;br /&gt;
				this.specialpage = &#039;Thanks&#039;;&lt;br /&gt;
				this.sep = &#039;/&#039;;&lt;br /&gt;
				this.article.value = this.diff !== &#039;prev&#039; ? this.diff : this.oldid;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;unwatch&#039;:&lt;br /&gt;
			case &#039;watch&#039;:&lt;br /&gt;
				this.print = magicWatchLink;&lt;br /&gt;
				this.action =&lt;br /&gt;
					this.id +&lt;br /&gt;
					&#039;&amp;amp;autowatchlist=1&amp;amp;autoimpl=&#039; +&lt;br /&gt;
					popupString(&#039;autoedit_version&#039;) +&lt;br /&gt;
					&#039;&amp;amp;actoken=&#039; +&lt;br /&gt;
					autoClickToken();&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;history&#039;:&lt;br /&gt;
			case &#039;historyfeed&#039;:&lt;br /&gt;
			case &#039;unprotect&#039;:&lt;br /&gt;
			case &#039;protect&#039;:&lt;br /&gt;
				this.print = wikiLink;&lt;br /&gt;
				this.action = this.id;&lt;br /&gt;
				break;&lt;br /&gt;
&lt;br /&gt;
			case &#039;delete&#039;:&lt;br /&gt;
				this.print = wikiLink;&lt;br /&gt;
				this.action = &#039;delete&#039;;&lt;br /&gt;
				if (this.article.namespaceId() == pg.nsImageId) {&lt;br /&gt;
					const img = this.article.stripNamespace();&lt;br /&gt;
					this.action += &#039;&amp;amp;image=&#039; + img;&lt;br /&gt;
				}&lt;br /&gt;
				break;&lt;br /&gt;
&lt;br /&gt;
			case &#039;markpatrolled&#039;:&lt;br /&gt;
			case &#039;edit&#039;: // editOld should keep the oldid, but edit should not.&lt;br /&gt;
				delete this.oldid;&lt;br /&gt;
			/* fall through */&lt;br /&gt;
			case &#039;view&#039;:&lt;br /&gt;
			case &#039;purge&#039;:&lt;br /&gt;
			case &#039;render&#039;:&lt;br /&gt;
				this.print = wikiLink;&lt;br /&gt;
				this.action = this.id;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;raw&#039;:&lt;br /&gt;
				this.print = wikiLink;&lt;br /&gt;
				this.action = &#039;raw&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;new&#039;:&lt;br /&gt;
				this.print = wikiLink;&lt;br /&gt;
				this.action = &#039;edit&amp;amp;section=new&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;mainlink&#039;:&lt;br /&gt;
				if (typeof this.text == &#039;undefined&#039;) {&lt;br /&gt;
					this.text = this.article.toString().entify();&lt;br /&gt;
				}&lt;br /&gt;
				if (getValueOf(&#039;popupSimplifyMainLink&#039;) &amp;amp;&amp;amp; isInStrippableNamespace(this.article)) {&lt;br /&gt;
					// only show the /subpage part of the title text&lt;br /&gt;
					const s = this.text.split(&#039;/&#039;);&lt;br /&gt;
					this.text = s[s.length - 1];&lt;br /&gt;
					if (this.text === &#039;&#039; &amp;amp;&amp;amp; s.length &amp;gt; 1) {&lt;br /&gt;
						this.text = s[s.length - 2];&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				this.print = titledWikiLink;&lt;br /&gt;
				if (&lt;br /&gt;
					typeof this.title === &#039;undefined&#039; &amp;amp;&amp;amp;&lt;br /&gt;
					pg.current.link &amp;amp;&amp;amp;&lt;br /&gt;
					typeof pg.current.link.href !== &#039;undefined&#039;&lt;br /&gt;
				) {&lt;br /&gt;
					this.title = safeDecodeURI(&lt;br /&gt;
						pg.current.link.originalTitle ? pg.current.link.originalTitle : this.article&lt;br /&gt;
					);&lt;br /&gt;
					if (typeof this.oldid !== &#039;undefined&#039; &amp;amp;&amp;amp; this.oldid) {&lt;br /&gt;
						this.title = tprintf(&#039;Revision %s of %s&#039;, [this.oldid, this.title]);&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				this.action = &#039;view&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;userPage&#039;:&lt;br /&gt;
			case &#039;article&#039;:&lt;br /&gt;
			case &#039;monobook&#039;:&lt;br /&gt;
			case &#039;editMonobook&#039;:&lt;br /&gt;
			case &#039;editArticle&#039;:&lt;br /&gt;
				delete this.oldid;&lt;br /&gt;
				//alert(this.id+&#039;\n&#039;+this.article + &#039;\n&#039;+ typeof this.article);&lt;br /&gt;
				this.article = this.article.articleFromTalkOrArticle();&lt;br /&gt;
				//alert(this.id+&#039;\n&#039;+this.article + &#039;\n&#039;+ typeof this.article);&lt;br /&gt;
				this.print = wikiLink;&lt;br /&gt;
				if (this.id.indexOf(&#039;edit&#039;) === 0) {&lt;br /&gt;
					this.action = &#039;edit&#039;;&lt;br /&gt;
				} else {&lt;br /&gt;
					this.action = &#039;view&#039;;&lt;br /&gt;
				}&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;userTalk&#039;:&lt;br /&gt;
			case &#039;talk&#039;:&lt;br /&gt;
				this.article = this.article.talkPage();&lt;br /&gt;
				delete this.oldid;&lt;br /&gt;
				this.print = wikiLink;&lt;br /&gt;
				this.action = &#039;view&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;arin&#039;:&lt;br /&gt;
				this.print = arinLink;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;count&#039;:&lt;br /&gt;
				this.print = editCounterLink;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;google&#039;:&lt;br /&gt;
				this.print = googleLink;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;editors&#039;:&lt;br /&gt;
				this.print = editorListLink;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;globalsearch&#039;:&lt;br /&gt;
				this.print = globalSearchLink;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;lastEdit&#039;:&lt;br /&gt;
				this.print = titledDiffLink;&lt;br /&gt;
				this.title = popupString(&#039;Show the last edit&#039;);&lt;br /&gt;
				this.from = &#039;prev&#039;;&lt;br /&gt;
				this.to = &#039;cur&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;oldEdit&#039;:&lt;br /&gt;
				this.print = titledDiffLink;&lt;br /&gt;
				this.title = popupString(&#039;Show the edit made to get revision&#039;) + &#039; &#039; + this.oldid;&lt;br /&gt;
				this.from = &#039;prev&#039;;&lt;br /&gt;
				this.to = this.oldid;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;editOld&#039;:&lt;br /&gt;
				this.print = wikiLink;&lt;br /&gt;
				this.action = &#039;edit&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;undo&#039;:&lt;br /&gt;
				this.print = wikiLink;&lt;br /&gt;
				this.action = &#039;edit&amp;amp;undo=&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;revert&#039;:&lt;br /&gt;
				this.print = wikiLink;&lt;br /&gt;
				this.action = &#039;revert&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;nullEdit&#039;:&lt;br /&gt;
				this.print = wikiLink;&lt;br /&gt;
				this.action = &#039;nullEdit&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;diffCur&#039;:&lt;br /&gt;
				this.print = titledDiffLink;&lt;br /&gt;
				this.title = tprintf(&#039;Show changes since revision %s&#039;, [this.oldid]);&lt;br /&gt;
				this.from = this.oldid;&lt;br /&gt;
				this.to = &#039;cur&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;editUserTalk&#039;:&lt;br /&gt;
			case &#039;editTalk&#039;:&lt;br /&gt;
				delete this.oldid;&lt;br /&gt;
				this.article = this.article.talkPage();&lt;br /&gt;
				this.action = &#039;edit&#039;;&lt;br /&gt;
				this.print = wikiLink;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;newUserTalk&#039;:&lt;br /&gt;
			case &#039;newTalk&#039;:&lt;br /&gt;
				this.article = this.article.talkPage();&lt;br /&gt;
				this.action = &#039;edit&amp;amp;section=new&#039;;&lt;br /&gt;
				this.print = wikiLink;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;lastContrib&#039;:&lt;br /&gt;
			case &#039;sinceMe&#039;:&lt;br /&gt;
				this.print = magicHistoryLink;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;togglePreviews&#039;:&lt;br /&gt;
				this.text = popupString(pg.option.simplePopups ? &#039;enable previews&#039; : &#039;disable previews&#039;);&lt;br /&gt;
			/* fall through */&lt;br /&gt;
			case &#039;disablePopups&#039;:&lt;br /&gt;
			case &#039;purgePopups&#039;:&lt;br /&gt;
				this.print = popupMenuLink;&lt;br /&gt;
				break;&lt;br /&gt;
			default:&lt;br /&gt;
				this.print = function () {&lt;br /&gt;
					return &#039;Unknown navlink type: &#039; + String(this.id);&lt;br /&gt;
				};&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
	//&lt;br /&gt;
	//  end navlinks&lt;br /&gt;
	//////////////////////////////////////////////////&lt;br /&gt;
	// ENDFILE: navlinks.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: shortcutkeys.js&lt;br /&gt;
	function popupHandleKeypress(evt) {&lt;br /&gt;
		const keyCode = window.event ? window.event.keyCode : evt.keyCode ? evt.keyCode : evt.which;&lt;br /&gt;
		if (!keyCode || !pg.current.link || !pg.current.link.navpopup) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (keyCode == 27) {&lt;br /&gt;
			// escape&lt;br /&gt;
			killPopup();&lt;br /&gt;
			return false; // swallow keypress&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const letter = String.fromCharCode(keyCode);&lt;br /&gt;
		const links = pg.current.link.navpopup.mainDiv.getElementsByTagName(&#039;A&#039;);&lt;br /&gt;
		let startLink = 0;&lt;br /&gt;
		let i, j;&lt;br /&gt;
&lt;br /&gt;
		if (popupHandleKeypress.lastPopupLinkSelected) {&lt;br /&gt;
			for (i = 0; i &amp;lt; links.length; ++i) {&lt;br /&gt;
				if (links[i] == popupHandleKeypress.lastPopupLinkSelected) {&lt;br /&gt;
					startLink = i;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		for (j = 0; j &amp;lt; links.length; ++j) {&lt;br /&gt;
			i = (startLink + j + 1) % links.length;&lt;br /&gt;
			if (links[i].getAttribute(&#039;popupkey&#039;) == letter) {&lt;br /&gt;
				if (evt &amp;amp;&amp;amp; evt.preventDefault) {&lt;br /&gt;
					evt.preventDefault();&lt;br /&gt;
				}&lt;br /&gt;
				links[i].focus();&lt;br /&gt;
				popupHandleKeypress.lastPopupLinkSelected = links[i];&lt;br /&gt;
				return false; // swallow keypress&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// pass keypress on&lt;br /&gt;
		if (document.oldPopupOnkeypress) {&lt;br /&gt;
			return document.oldPopupOnkeypress(evt);&lt;br /&gt;
		}&lt;br /&gt;
		return true;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function addPopupShortcuts() {&lt;br /&gt;
		if (document.onkeypress != popupHandleKeypress) {&lt;br /&gt;
			document.oldPopupOnkeypress = document.onkeypress;&lt;br /&gt;
		}&lt;br /&gt;
		document.onkeypress = popupHandleKeypress;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function rmPopupShortcuts() {&lt;br /&gt;
		popupHandleKeypress.lastPopupLinkSelected = null;&lt;br /&gt;
		try {&lt;br /&gt;
			if (document.oldPopupOnkeypress &amp;amp;&amp;amp; document.oldPopupOnkeypress == popupHandleKeypress) {&lt;br /&gt;
				// panic&lt;br /&gt;
				document.onkeypress = null; //function () {};&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			document.onkeypress = document.oldPopupOnkeypress;&lt;br /&gt;
		} catch (nasties) {&lt;br /&gt;
			/* IE goes here */&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function addLinkProperty(html, property) {&lt;br /&gt;
		// take &amp;quot;&amp;lt;a href=...&amp;gt;...&amp;lt;/a&amp;gt; and add a property&lt;br /&gt;
		// not sophisticated at all, easily broken&lt;br /&gt;
		const i = html.indexOf(&#039;&amp;gt;&#039;);&lt;br /&gt;
		if (i &amp;lt; 0) {&lt;br /&gt;
			return html;&lt;br /&gt;
		}&lt;br /&gt;
		return html.substring(0, i) + &#039; &#039; + property + html.substring(i);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function addPopupShortcut(html, key) {&lt;br /&gt;
		if (!getValueOf(&#039;popupShortcutKeys&#039;)) {&lt;br /&gt;
			return html;&lt;br /&gt;
		}&lt;br /&gt;
		const ret = addLinkProperty(html, &#039;popupkey=&amp;quot;&#039; + key + &#039;&amp;quot;&#039;);&lt;br /&gt;
		if (key == &#039; &#039;) {&lt;br /&gt;
			key = popupString(&#039;spacebar&#039;);&lt;br /&gt;
		}&lt;br /&gt;
		return ret.replace(/^(.*?)(title=&amp;quot;)(.*?)(&amp;quot;.*)$/i, &#039;$1$2$3 [&#039; + key + &#039;]$4&#039;);&lt;br /&gt;
	}&lt;br /&gt;
	// ENDFILE: shortcutkeys.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: diffpreview.js&lt;br /&gt;
	/**&lt;br /&gt;
	 * Load diff data.&lt;br /&gt;
	 *&lt;br /&gt;
	 * lets jump through hoops to find the rev ids we need to retrieve&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param {Title} article&lt;br /&gt;
	 * @param {string} oldid&lt;br /&gt;
	 * @param {string} diff&lt;br /&gt;
	 * @param {Navpopup} navpop&lt;br /&gt;
	 */&lt;br /&gt;
	function loadDiff(article, oldid, diff, navpop) {&lt;br /&gt;
		navpop.diffData = { oldRev: {}, newRev: {} };&lt;br /&gt;
		mw.loader.using(&#039;mediawiki.api&#039;).then(() =&amp;gt; {&lt;br /&gt;
			const api = getMwApi();&lt;br /&gt;
			const params = {&lt;br /&gt;
				action: &#039;compare&#039;,&lt;br /&gt;
				prop: &#039;ids|title&#039;,&lt;br /&gt;
			};&lt;br /&gt;
			params.fromtitle = article.toString();&lt;br /&gt;
&lt;br /&gt;
			switch (diff) {&lt;br /&gt;
				case &#039;cur&#039;:&lt;br /&gt;
					switch (oldid) {&lt;br /&gt;
						case null:&lt;br /&gt;
						case &#039;&#039;:&lt;br /&gt;
						case &#039;prev&#039;:&lt;br /&gt;
							// this can only work if we have the title&lt;br /&gt;
							// cur -&amp;gt; prev&lt;br /&gt;
							params.torelative = &#039;prev&#039;;&lt;br /&gt;
							break;&lt;br /&gt;
						default:&lt;br /&gt;
							params.fromrev = oldid;&lt;br /&gt;
							params.torelative = &#039;cur&#039;;&lt;br /&gt;
							break;&lt;br /&gt;
					}&lt;br /&gt;
					break;&lt;br /&gt;
				case &#039;prev&#039;:&lt;br /&gt;
					if (oldid &amp;amp;&amp;amp; oldid !== &#039;cur&#039;) {&lt;br /&gt;
						params.fromrev = oldid;&lt;br /&gt;
					}&lt;br /&gt;
					params.torelative = &#039;prev&#039;;&lt;br /&gt;
					break;&lt;br /&gt;
				case &#039;next&#039;:&lt;br /&gt;
					params.fromrev = oldid || 0;&lt;br /&gt;
					params.torelative = &#039;next&#039;;&lt;br /&gt;
					break;&lt;br /&gt;
				default:&lt;br /&gt;
					params.fromrev = oldid || 0;&lt;br /&gt;
					params.torev = diff || 0;&lt;br /&gt;
					break;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			api.get(params).then((data) =&amp;gt; {&lt;br /&gt;
				navpop.diffData.oldRev.revid = data.compare.fromrevid;&lt;br /&gt;
				navpop.diffData.newRev.revid = data.compare.torevid;&lt;br /&gt;
&lt;br /&gt;
				addReviewLink(navpop, &#039;popupMiscTools&#039;);&lt;br /&gt;
&lt;br /&gt;
				const go = function () {&lt;br /&gt;
					pendingNavpopTask(navpop);&lt;br /&gt;
					let url = pg.wiki.apiwikibase + &#039;?format=json&amp;amp;formatversion=2&amp;amp;action=query&amp;amp;&#039;;&lt;br /&gt;
&lt;br /&gt;
					url += &#039;revids=&#039; + navpop.diffData.oldRev.revid + &#039;|&#039; + navpop.diffData.newRev.revid;&lt;br /&gt;
					url += &#039;&amp;amp;prop=revisions&amp;amp;rvslots=main&amp;amp;rvprop=ids|timestamp|content&#039;;&lt;br /&gt;
&lt;br /&gt;
					getPageWithCaching(url, doneDiff, navpop);&lt;br /&gt;
&lt;br /&gt;
					return true; // remove hook once run&lt;br /&gt;
				};&lt;br /&gt;
				if (navpop.visible || !getValueOf(&#039;popupLazyDownloads&#039;)) {&lt;br /&gt;
					go();&lt;br /&gt;
				} else {&lt;br /&gt;
					navpop.addHook(go, &#039;unhide&#039;, &#039;before&#039;, &#039;DOWNLOAD_DIFFS&#039;);&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Put a &amp;quot;mark patrolled&amp;quot; link to an element target&lt;br /&gt;
	// TODO: Allow patrol a revision, as well as a diff&lt;br /&gt;
	function addReviewLink(navpop, target) {&lt;br /&gt;
		if (!pg.user.canReview) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		// If &#039;newRev&#039; is older than &#039;oldRev&#039; than it could be confusing, so we do not show the review link.&lt;br /&gt;
		if (navpop.diffData.newRev.revid &amp;lt;= navpop.diffData.oldRev.revid) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		const params = {&lt;br /&gt;
			action: &#039;query&#039;,&lt;br /&gt;
			prop: &#039;info|flagged&#039;,&lt;br /&gt;
			revids: navpop.diffData.oldRev.revid,&lt;br /&gt;
			formatversion: 2,&lt;br /&gt;
		};&lt;br /&gt;
		getMwApi()&lt;br /&gt;
			.get(params)&lt;br /&gt;
			.then((data) =&amp;gt; {&lt;br /&gt;
				const stable_revid =&lt;br /&gt;
					(data.query.pages[0].flagged &amp;amp;&amp;amp; data.query.pages[0].flagged.stable_revid) || 0;&lt;br /&gt;
				// The diff can be reviewed if the old version is the last reviewed version&lt;br /&gt;
				// TODO: Other possible conditions that we may want to implement instead of this one:&lt;br /&gt;
				//  * old version is patrolled and the new version is not patrolled&lt;br /&gt;
				//  * old version is patrolled and the new version is more recent than the last reviewed version&lt;br /&gt;
				if (stable_revid == navpop.diffData.oldRev.revid) {&lt;br /&gt;
					const a = document.createElement(&#039;a&#039;);&lt;br /&gt;
					a.innerHTML = popupString(&#039;mark patrolled&#039;);&lt;br /&gt;
					a.title = popupString(&#039;markpatrolledHint&#039;);&lt;br /&gt;
					a.onclick = function () {&lt;br /&gt;
						const params = {&lt;br /&gt;
							action: &#039;review&#039;,&lt;br /&gt;
							revid: navpop.diffData.newRev.revid,&lt;br /&gt;
							comment: tprintf(&#039;defaultpopupReviewedSummary&#039;, [&lt;br /&gt;
								navpop.diffData.oldRev.revid,&lt;br /&gt;
								navpop.diffData.newRev.revid,&lt;br /&gt;
							]),&lt;br /&gt;
						};&lt;br /&gt;
						getMwApi()&lt;br /&gt;
							.postWithToken(&#039;csrf&#039;, params)&lt;br /&gt;
							.done(() =&amp;gt; {&lt;br /&gt;
								a.style.display = &#039;none&#039;;&lt;br /&gt;
								// TODO: Update current page and other already constructed popups&lt;br /&gt;
							})&lt;br /&gt;
							.fail(() =&amp;gt; {&lt;br /&gt;
								alert(popupString(&#039;Could not marked this edit as patrolled&#039;));&lt;br /&gt;
							});&lt;br /&gt;
					};&lt;br /&gt;
					setPopupHTML(a, target, navpop.idNumber, null, true);&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function doneDiff(download) {&lt;br /&gt;
		if (!download.owner || !download.owner.diffData) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		const navpop = download.owner;&lt;br /&gt;
		completedNavpopTask(navpop);&lt;br /&gt;
&lt;br /&gt;
		let pages,&lt;br /&gt;
			revisions = [];&lt;br /&gt;
		try {&lt;br /&gt;
			// Process the downloads&lt;br /&gt;
			pages = getJsObj(download.data).query.pages;&lt;br /&gt;
			for (var i = 0; i &amp;lt; pages.length; i++) {&lt;br /&gt;
				revisions = revisions.concat(pages[i].revisions);&lt;br /&gt;
			}&lt;br /&gt;
			for (i = 0; i &amp;lt; revisions.length; i++) {&lt;br /&gt;
				if (revisions[i].revid == navpop.diffData.oldRev.revid) {&lt;br /&gt;
					navpop.diffData.oldRev.revision = revisions[i];&lt;br /&gt;
				} else if (revisions[i].revid == navpop.diffData.newRev.revid) {&lt;br /&gt;
					navpop.diffData.newRev.revision = revisions[i];&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		} catch (someError) {&lt;br /&gt;
			errlog(&#039;Could not get diff&#039;);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		insertDiff(navpop);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function rmBoringLines(a, b, context) {&lt;br /&gt;
		if (typeof context == &#039;undefined&#039;) {&lt;br /&gt;
			context = 2;&lt;br /&gt;
		}&lt;br /&gt;
		// this is fairly slow... i think it&#039;s quicker than doing a word-based diff from the off, though&lt;br /&gt;
		const aa = [],&lt;br /&gt;
			aaa = [];&lt;br /&gt;
		const bb = [],&lt;br /&gt;
			bbb = [];&lt;br /&gt;
		let i, j;&lt;br /&gt;
&lt;br /&gt;
		// first, gather all disconnected nodes in a and all crossing nodes in a and b&lt;br /&gt;
		for (i = 0; i &amp;lt; a.length; ++i) {&lt;br /&gt;
			if (!a[i].paired) {&lt;br /&gt;
				aa[i] = 1;&lt;br /&gt;
			} else if (countCrossings(b, a, i, true)) {&lt;br /&gt;
				aa[i] = 1;&lt;br /&gt;
				bb[a[i].row] = 1;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// pick up remaining disconnected nodes in b&lt;br /&gt;
		for (i = 0; i &amp;lt; b.length; ++i) {&lt;br /&gt;
			if (bb[i] == 1) {&lt;br /&gt;
				continue;&lt;br /&gt;
			}&lt;br /&gt;
			if (!b[i].paired) {&lt;br /&gt;
				bb[i] = 1;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// another pass to gather context: we want the neighbours of included nodes which are not&lt;br /&gt;
		// yet included we have to add in partners of these nodes, but we don&#039;t want to add context&lt;br /&gt;
		// for *those* nodes in the next pass&lt;br /&gt;
		for (i = 0; i &amp;lt; b.length; ++i) {&lt;br /&gt;
			if (bb[i] == 1) {&lt;br /&gt;
				for (j = Math.max(0, i - context); j &amp;lt; Math.min(b.length, i + context); ++j) {&lt;br /&gt;
					if (!bb[j]) {&lt;br /&gt;
						bb[j] = 1;&lt;br /&gt;
						aa[b[j].row] = 0.5;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		for (i = 0; i &amp;lt; a.length; ++i) {&lt;br /&gt;
			if (aa[i] == 1) {&lt;br /&gt;
				for (j = Math.max(0, i - context); j &amp;lt; Math.min(a.length, i + context); ++j) {&lt;br /&gt;
					if (!aa[j]) {&lt;br /&gt;
						aa[j] = 1;&lt;br /&gt;
						bb[a[j].row] = 0.5;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		for (i = 0; i &amp;lt; bb.length; ++i) {&lt;br /&gt;
			if (bb[i] &amp;gt; 0) {&lt;br /&gt;
				// it&#039;s a row we need&lt;br /&gt;
				if (b[i].paired) {&lt;br /&gt;
					bbb.push(b[i].text);&lt;br /&gt;
				} // joined; partner should be in aa&lt;br /&gt;
				else {&lt;br /&gt;
					bbb.push(b[i]);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		for (i = 0; i &amp;lt; aa.length; ++i) {&lt;br /&gt;
			if (aa[i] &amp;gt; 0) {&lt;br /&gt;
				// it&#039;s a row we need&lt;br /&gt;
				if (a[i].paired) {&lt;br /&gt;
					aaa.push(a[i].text);&lt;br /&gt;
				} // joined; partner should be in aa&lt;br /&gt;
				else {&lt;br /&gt;
					aaa.push(a[i]);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		return { a: aaa, b: bbb };&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function stripOuterCommonLines(a, b, context) {&lt;br /&gt;
		let i = 0;&lt;br /&gt;
		while (i &amp;lt; a.length &amp;amp;&amp;amp; i &amp;lt; b.length &amp;amp;&amp;amp; a[i] == b[i]) {&lt;br /&gt;
			++i;&lt;br /&gt;
		}&lt;br /&gt;
		let j = a.length - 1;&lt;br /&gt;
		let k = b.length - 1;&lt;br /&gt;
		while (j &amp;gt;= 0 &amp;amp;&amp;amp; k &amp;gt;= 0 &amp;amp;&amp;amp; a[j] == b[k]) {&lt;br /&gt;
			--j;&lt;br /&gt;
			--k;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		return {&lt;br /&gt;
			a: a.slice(Math.max(0, i - 1 - context), Math.min(a.length + 1, j + context + 1)),&lt;br /&gt;
			b: b.slice(Math.max(0, i - 1 - context), Math.min(b.length + 1, k + context + 1)),&lt;br /&gt;
		};&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function insertDiff(navpop) {&lt;br /&gt;
		// for speed reasons, we first do a line-based diff, discard stuff that seems boring, then&lt;br /&gt;
		// do a word-based diff&lt;br /&gt;
		// FIXME: sometimes this gives misleading diffs as distant chunks are squashed together&lt;br /&gt;
		let oldlines = navpop.diffData.oldRev.revision.slots.main.content.split(&#039;\n&#039;);&lt;br /&gt;
		let newlines = navpop.diffData.newRev.revision.slots.main.content.split(&#039;\n&#039;);&lt;br /&gt;
		let inner = stripOuterCommonLines(oldlines, newlines, getValueOf(&#039;popupDiffContextLines&#039;));&lt;br /&gt;
		oldlines = inner.a;&lt;br /&gt;
		newlines = inner.b;&lt;br /&gt;
		let truncated = false;&lt;br /&gt;
		getValueOf(&#039;popupDiffMaxLines&#039;);&lt;br /&gt;
		if (&lt;br /&gt;
			oldlines.length &amp;gt; pg.option.popupDiffMaxLines ||&lt;br /&gt;
			newlines.length &amp;gt; pg.option.popupDiffMaxLines&lt;br /&gt;
		) {&lt;br /&gt;
			// truncate&lt;br /&gt;
			truncated = true;&lt;br /&gt;
			inner = stripOuterCommonLines(&lt;br /&gt;
				oldlines.slice(0, pg.option.popupDiffMaxLines),&lt;br /&gt;
				newlines.slice(0, pg.option.popupDiffMaxLines),&lt;br /&gt;
				pg.option.popupDiffContextLines&lt;br /&gt;
			);&lt;br /&gt;
			oldlines = inner.a;&lt;br /&gt;
			newlines = inner.b;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const lineDiff = diff(oldlines, newlines);&lt;br /&gt;
		const lines2 = rmBoringLines(lineDiff.o, lineDiff.n);&lt;br /&gt;
		const oldlines2 = lines2.a;&lt;br /&gt;
		const newlines2 = lines2.b;&lt;br /&gt;
&lt;br /&gt;
		const simpleSplit = !String.prototype.parenSplit.isNative;&lt;br /&gt;
		let html = &#039;&amp;lt;hr /&amp;gt;&#039;;&lt;br /&gt;
		if (getValueOf(&#039;popupDiffDates&#039;)) {&lt;br /&gt;
			html += diffDatesTable(navpop);&lt;br /&gt;
			html += &#039;&amp;lt;hr /&amp;gt;&#039;;&lt;br /&gt;
		}&lt;br /&gt;
		html += shortenDiffString(&lt;br /&gt;
			diffString(oldlines2.join(&#039;\n&#039;), newlines2.join(&#039;\n&#039;), simpleSplit),&lt;br /&gt;
			getValueOf(&#039;popupDiffContextCharacters&#039;)&lt;br /&gt;
		).join(&#039;&amp;lt;hr /&amp;gt;&#039;);&lt;br /&gt;
		setPopupTipsAndHTML(&lt;br /&gt;
			html.split(&#039;\n&#039;).join(&#039;&amp;lt;br&amp;gt;&#039;) +&lt;br /&gt;
				(truncated ?&lt;br /&gt;
					&#039;&amp;lt;hr /&amp;gt;&amp;lt;b&amp;gt;&#039; + popupString(&#039;Diff truncated for performance reasons&#039;) + &#039;&amp;lt;/b&amp;gt;&#039; :&lt;br /&gt;
					&#039;&#039;),&lt;br /&gt;
			&#039;popupPreview&#039;,&lt;br /&gt;
			navpop.idNumber&lt;br /&gt;
		);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function diffDatesTable(navpop) {&lt;br /&gt;
		let html = &#039;&amp;lt;table class=&amp;quot;popup_diff_dates&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
		html += diffDatesTableRow(navpop.diffData.newRev.revision, tprintf(&#039;New revision&#039;));&lt;br /&gt;
		html += diffDatesTableRow(navpop.diffData.oldRev.revision, tprintf(&#039;Old revision&#039;));&lt;br /&gt;
		html += &#039;&amp;lt;/table&amp;gt;&#039;;&lt;br /&gt;
		return html;&lt;br /&gt;
	}&lt;br /&gt;
	function diffDatesTableRow(revision, label) {&lt;br /&gt;
		let txt = &#039;&#039;;&lt;br /&gt;
		const lastModifiedDate = new Date(revision.timestamp);&lt;br /&gt;
&lt;br /&gt;
		txt = formattedDateTime(lastModifiedDate);&lt;br /&gt;
&lt;br /&gt;
		const revlink = generalLink({&lt;br /&gt;
			url: mw.config.get(&#039;wgScript&#039;) + &#039;?oldid=&#039; + revision.revid,&lt;br /&gt;
			text: label,&lt;br /&gt;
			title: label,&lt;br /&gt;
		});&lt;br /&gt;
		return simplePrintf(&#039;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;%s&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;%s&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&#039;, [revlink, txt]);&lt;br /&gt;
	}&lt;br /&gt;
	// ENDFILE: diffpreview.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: links.js&lt;br /&gt;
	/////////////////////&lt;br /&gt;
	// LINK GENERATION //&lt;br /&gt;
	/////////////////////&lt;br /&gt;
&lt;br /&gt;
	// titledDiffLink --&amp;gt; titledWikiLink --&amp;gt; generalLink&lt;br /&gt;
	// wikiLink	   --&amp;gt; titledWikiLink --&amp;gt; generalLink&lt;br /&gt;
	// editCounterLink --&amp;gt; generalLink&lt;br /&gt;
&lt;br /&gt;
	// TODO Make these functions return Element objects, not just raw HTML strings.&lt;br /&gt;
&lt;br /&gt;
	function titledDiffLink(l) {&lt;br /&gt;
		// article, text, title, from, to) {&lt;br /&gt;
		return titledWikiLink({&lt;br /&gt;
			article: l.article,&lt;br /&gt;
			action: l.to + &#039;&amp;amp;oldid=&#039; + l.from,&lt;br /&gt;
			newWin: l.newWin,&lt;br /&gt;
			noPopup: l.noPopup,&lt;br /&gt;
			text: l.text,&lt;br /&gt;
			title: l.title,&lt;br /&gt;
			/* hack: no oldid here */&lt;br /&gt;
			actionName: &#039;diff&#039;,&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function wikiLink(l) {&lt;br /&gt;
		//{article:article, action:action, text:text, oldid, newid}) {&lt;br /&gt;
		if (&lt;br /&gt;
			!(typeof l.article == typeof {} &amp;amp;&amp;amp; typeof l.action == typeof &#039;&#039; &amp;amp;&amp;amp; typeof l.text == typeof &#039;&#039;)&lt;br /&gt;
		) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
		if (typeof l.oldid == &#039;undefined&#039;) {&lt;br /&gt;
			l.oldid = null;&lt;br /&gt;
		}&lt;br /&gt;
		const savedOldid = l.oldid;&lt;br /&gt;
		if (!/^(edit|view|revert|render)$|^raw/.test(l.action)) {&lt;br /&gt;
			l.oldid = null;&lt;br /&gt;
		}&lt;br /&gt;
		let hint = popupString(l.action + &#039;Hint&#039;); // revertHint etc etc etc&lt;br /&gt;
		const oldidData = [l.oldid, safeDecodeURI(l.article)];&lt;br /&gt;
		let revisionString = tprintf(&#039;revision %s of %s&#039;, oldidData);&lt;br /&gt;
		log(&#039;revisionString=&#039; + revisionString);&lt;br /&gt;
		switch (l.action) {&lt;br /&gt;
			case &#039;edit&amp;amp;section=new&#039;:&lt;br /&gt;
				hint = popupString(&#039;newSectionHint&#039;);&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;edit&amp;amp;undo=&#039;:&lt;br /&gt;
				if (l.diff &amp;amp;&amp;amp; l.diff != &#039;prev&#039; &amp;amp;&amp;amp; savedOldid) {&lt;br /&gt;
					l.action += l.diff + &#039;&amp;amp;undoafter=&#039; + savedOldid;&lt;br /&gt;
				} else if (savedOldid) {&lt;br /&gt;
					l.action += savedOldid;&lt;br /&gt;
				}&lt;br /&gt;
				hint = popupString(&#039;undoHint&#039;);&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;raw&amp;amp;ctype=text/css&#039;:&lt;br /&gt;
				hint = popupString(&#039;rawHint&#039;);&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;revert&#039;:&lt;br /&gt;
				var p = parseParams(pg.current.link.href);&lt;br /&gt;
				l.action =&lt;br /&gt;
					&#039;edit&amp;amp;autoclick=wpSave&amp;amp;actoken=&#039; +&lt;br /&gt;
					autoClickToken() +&lt;br /&gt;
					&#039;&amp;amp;autoimpl=&#039; +&lt;br /&gt;
					popupString(&#039;autoedit_version&#039;) +&lt;br /&gt;
					&#039;&amp;amp;autosummary=&#039; +&lt;br /&gt;
					revertSummary(l.oldid, p.diff);&lt;br /&gt;
				if (p.diff == &#039;prev&#039;) {&lt;br /&gt;
					l.action += &#039;&amp;amp;direction=prev&#039;;&lt;br /&gt;
					revisionString = tprintf(&#039;the revision prior to revision %s of %s&#039;, oldidData);&lt;br /&gt;
				}&lt;br /&gt;
				if (getValueOf(&#039;popupRevertSummaryPrompt&#039;)) {&lt;br /&gt;
					l.action += &#039;&amp;amp;autosummaryprompt=true&#039;;&lt;br /&gt;
				}&lt;br /&gt;
				if (getValueOf(&#039;popupMinorReverts&#039;)) {&lt;br /&gt;
					l.action += &#039;&amp;amp;autominor=true&#039;;&lt;br /&gt;
				}&lt;br /&gt;
				log(&#039;revisionString is now &#039; + revisionString);&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;nullEdit&#039;:&lt;br /&gt;
				l.action =&lt;br /&gt;
					&#039;edit&amp;amp;autoclick=wpSave&amp;amp;actoken=&#039; +&lt;br /&gt;
					autoClickToken() +&lt;br /&gt;
					&#039;&amp;amp;autoimpl=&#039; +&lt;br /&gt;
					popupString(&#039;autoedit_version&#039;) +&lt;br /&gt;
					&#039;&amp;amp;autosummary=null&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;historyfeed&#039;:&lt;br /&gt;
				l.action = &#039;history&amp;amp;feed=rss&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;markpatrolled&#039;:&lt;br /&gt;
				l.action = &#039;markpatrolled&amp;amp;rcid=&#039; + l.rcid;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (hint) {&lt;br /&gt;
			if (l.oldid) {&lt;br /&gt;
				hint = simplePrintf(hint, [revisionString]);&lt;br /&gt;
			} else {&lt;br /&gt;
				hint = simplePrintf(hint, [safeDecodeURI(l.article)]);&lt;br /&gt;
			}&lt;br /&gt;
		} else {&lt;br /&gt;
			hint = safeDecodeURI(l.article + &#039;&amp;amp;action=&#039; + l.action) + l.oldid ? &#039;&amp;amp;oldid=&#039; + l.oldid : &#039;&#039;;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		return titledWikiLink({&lt;br /&gt;
			article: l.article,&lt;br /&gt;
			action: l.action,&lt;br /&gt;
			text: l.text,&lt;br /&gt;
			newWin: l.newWin,&lt;br /&gt;
			title: hint,&lt;br /&gt;
			oldid: l.oldid,&lt;br /&gt;
			noPopup: l.noPopup,&lt;br /&gt;
			onclick: l.onclick,&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function revertSummary(oldid, diff) {&lt;br /&gt;
		let ret = &#039;&#039;;&lt;br /&gt;
		if (diff == &#039;prev&#039;) {&lt;br /&gt;
			ret = getValueOf(&#039;popupQueriedRevertToPreviousSummary&#039;);&lt;br /&gt;
		} else {&lt;br /&gt;
			ret = getValueOf(&#039;popupQueriedRevertSummary&#039;);&lt;br /&gt;
		}&lt;br /&gt;
		return ret + &#039;&amp;amp;autorv=&#039; + oldid;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function titledWikiLink(l) {&lt;br /&gt;
		// possible properties of argument:&lt;br /&gt;
		// article, action, text, title, oldid, actionName, className, noPopup&lt;br /&gt;
		// oldid = null is fine here&lt;br /&gt;
&lt;br /&gt;
		// article and action are mandatory args&lt;br /&gt;
&lt;br /&gt;
		if (typeof l.article == &#039;undefined&#039; || typeof l.action == &#039;undefined&#039;) {&lt;br /&gt;
			errlog(&#039;got undefined article or action in titledWikiLink&#039;);&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const base = pg.wiki.titlebase + l.article.urlString();&lt;br /&gt;
		let url = base;&lt;br /&gt;
&lt;br /&gt;
		if (typeof l.actionName == &#039;undefined&#039; || !l.actionName) {&lt;br /&gt;
			l.actionName = &#039;action&#039;;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// no need to add &amp;amp;action=view, and this confuses anchors&lt;br /&gt;
		if (l.action != &#039;view&#039;) {&lt;br /&gt;
			url = base + &#039;&amp;amp;&#039; + l.actionName + &#039;=&#039; + l.action;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (typeof l.oldid != &#039;undefined&#039; &amp;amp;&amp;amp; l.oldid) {&lt;br /&gt;
			url += &#039;&amp;amp;oldid=&#039; + l.oldid;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		let cssClass = pg.misc.defaultNavlinkClassname;&lt;br /&gt;
		if (typeof l.className != &#039;undefined&#039; &amp;amp;&amp;amp; l.className) {&lt;br /&gt;
			cssClass = l.className;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		return generalNavLink({&lt;br /&gt;
			url: url,&lt;br /&gt;
			newWin: l.newWin,&lt;br /&gt;
			title: typeof l.title != &#039;undefined&#039; ? l.title : null,&lt;br /&gt;
			text: typeof l.text != &#039;undefined&#039; ? l.text : null,&lt;br /&gt;
			className: cssClass,&lt;br /&gt;
			noPopup: l.noPopup,&lt;br /&gt;
			onclick: l.onclick,&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	pg.fn.getLastContrib = function getLastContrib(wikipage, newWin) {&lt;br /&gt;
		getHistoryInfo(wikipage, (x) =&amp;gt; {&lt;br /&gt;
			processLastContribInfo(x, { page: wikipage, newWin: newWin });&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function processLastContribInfo(info, stuff) {&lt;br /&gt;
		if (!info.edits || !info.edits.length) {&lt;br /&gt;
			alert(&#039;Popups: an odd thing happened. Please retry.&#039;);&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (!info.firstNewEditor) {&lt;br /&gt;
			alert(&lt;br /&gt;
				tprintf(&#039;Only found one editor: %s made %s edits&#039;, [&lt;br /&gt;
					info.edits[0].editor,&lt;br /&gt;
					info.edits.length,&lt;br /&gt;
				])&lt;br /&gt;
			);&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		const newUrl =&lt;br /&gt;
			pg.wiki.titlebase +&lt;br /&gt;
			new Title(stuff.page).urlString() +&lt;br /&gt;
			&#039;&amp;amp;diff=cur&amp;amp;oldid=&#039; +&lt;br /&gt;
			info.firstNewEditor.oldid;&lt;br /&gt;
		displayUrl(newUrl, stuff.newWin);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	pg.fn.getDiffSinceMyEdit = function getDiffSinceMyEdit(wikipage, newWin) {&lt;br /&gt;
		getHistoryInfo(wikipage, (x) =&amp;gt; {&lt;br /&gt;
			processDiffSinceMyEdit(x, { page: wikipage, newWin: newWin });&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function processDiffSinceMyEdit(info, stuff) {&lt;br /&gt;
		if (!info.edits || !info.edits.length) {&lt;br /&gt;
			alert(&#039;Popups: something fishy happened. Please try again.&#039;);&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		const friendlyName = stuff.page.split(&#039;_&#039;).join(&#039; &#039;);&lt;br /&gt;
		if (!info.myLastEdit) {&lt;br /&gt;
			alert(&lt;br /&gt;
				tprintf(&amp;quot;Couldn&#039;t find an edit by %s\nin the last %s edits to\n%s&amp;quot;, [&lt;br /&gt;
					info.userName,&lt;br /&gt;
					getValueOf(&#039;popupHistoryLimit&#039;),&lt;br /&gt;
					friendlyName,&lt;br /&gt;
				])&lt;br /&gt;
			);&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (info.myLastEdit.index === 0) {&lt;br /&gt;
			alert(&lt;br /&gt;
				tprintf(&#039;%s seems to be the last editor to the page %s&#039;, [info.userName, friendlyName])&lt;br /&gt;
			);&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		const newUrl =&lt;br /&gt;
			pg.wiki.titlebase +&lt;br /&gt;
			new Title(stuff.page).urlString() +&lt;br /&gt;
			&#039;&amp;amp;diff=cur&amp;amp;oldid=&#039; +&lt;br /&gt;
			info.myLastEdit.oldid;&lt;br /&gt;
		displayUrl(newUrl, stuff.newWin);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function displayUrl(url, newWin) {&lt;br /&gt;
		if (newWin) {&lt;br /&gt;
			window.open(url);&lt;br /&gt;
		} else {&lt;br /&gt;
			document.location = url;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	pg.fn.purgePopups = function purgePopups() {&lt;br /&gt;
		processAllPopups(true);&lt;br /&gt;
		setupCache(); // deletes all cached items (not browser cached, though...)&lt;br /&gt;
		pg.option = {};&lt;br /&gt;
		abortAllDownloads();&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function processAllPopups(nullify, banish) {&lt;br /&gt;
		for (let i = 0; pg.current.links &amp;amp;&amp;amp; i &amp;lt; pg.current.links.length; ++i) {&lt;br /&gt;
			if (!pg.current.links[i].navpopup) {&lt;br /&gt;
				continue;&lt;br /&gt;
			}&lt;br /&gt;
			if (nullify || banish) {&lt;br /&gt;
				pg.current.links[i].navpopup.banish();&lt;br /&gt;
			}&lt;br /&gt;
			pg.current.links[i].simpleNoMore = false;&lt;br /&gt;
			if (nullify) {&lt;br /&gt;
				pg.current.links[i].navpopup = null;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	pg.fn.disablePopups = function disablePopups() {&lt;br /&gt;
		processAllPopups(false, true);&lt;br /&gt;
		setupTooltips(null, true);&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	pg.fn.togglePreviews = function togglePreviews() {&lt;br /&gt;
		processAllPopups(true, true);&lt;br /&gt;
		pg.option.simplePopups = !pg.option.simplePopups;&lt;br /&gt;
		abortAllDownloads();&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function magicWatchLink(l) {&lt;br /&gt;
		//Yuck!! Would require a thorough redesign to add this as a click event though ...&lt;br /&gt;
		l.onclick = simplePrintf(&amp;quot;pg.fn.modifyWatchlist(&#039;%s&#039;,&#039;%s&#039;);return false;&amp;quot;, [&lt;br /&gt;
			l.article.toString(true).split(&#039;\\&#039;).join(&#039;\\\\&#039;).split(&amp;quot;&#039;&amp;quot;).join(&amp;quot;\\&#039;&amp;quot;),&lt;br /&gt;
			this.id,&lt;br /&gt;
		]);&lt;br /&gt;
		return wikiLink(l);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	pg.fn.modifyWatchlist = function modifyWatchlist(title, action) {&lt;br /&gt;
		const reqData = {&lt;br /&gt;
			action: &#039;watch&#039;,&lt;br /&gt;
			formatversion: 2,&lt;br /&gt;
			titles: title,&lt;br /&gt;
			uselang: mw.config.get(&#039;wgUserLanguage&#039;),&lt;br /&gt;
		};&lt;br /&gt;
		if (action === &#039;unwatch&#039;) {&lt;br /&gt;
			reqData.unwatch = true;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Load the Addedwatchtext or Removedwatchtext message and show it&lt;br /&gt;
		const mwTitle = mw.Title.newFromText(title);&lt;br /&gt;
		let messageName;&lt;br /&gt;
		if (mwTitle &amp;amp;&amp;amp; mwTitle.getNamespaceId() &amp;gt; 0 &amp;amp;&amp;amp; mwTitle.getNamespaceId() % 2 === 1) {&lt;br /&gt;
			messageName = action === &#039;watch&#039; ? &#039;addedwatchtext-talk&#039; : &#039;removedwatchtext-talk&#039;;&lt;br /&gt;
		} else {&lt;br /&gt;
			messageName = action === &#039;watch&#039; ? &#039;addedwatchtext&#039; : &#039;removedwatchtext&#039;;&lt;br /&gt;
		}&lt;br /&gt;
		$.when(&lt;br /&gt;
			getMwApi().postWithToken(&#039;watch&#039;, reqData),&lt;br /&gt;
			getMwApi().loadMessagesIfMissing([messageName])&lt;br /&gt;
		).done(() =&amp;gt; {&lt;br /&gt;
			mw.notify(mw.message(messageName, title).parseDom());&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function magicHistoryLink(l) {&lt;br /&gt;
		// FIXME use onclick change href trick to sort this out instead of window.open&lt;br /&gt;
&lt;br /&gt;
		let jsUrl = &#039;&#039;,&lt;br /&gt;
			title = &#039;&#039;,&lt;br /&gt;
			onClick = &#039;&#039;;&lt;br /&gt;
		switch (l.id) {&lt;br /&gt;
			case &#039;lastContrib&#039;:&lt;br /&gt;
				onClick = simplePrintf(&amp;quot;pg.fn.getLastContrib(&#039;%s&#039;,%s)&amp;quot;, [&lt;br /&gt;
					l.article.toString(true).split(&#039;\\&#039;).join(&#039;\\\\&#039;).split(&amp;quot;&#039;&amp;quot;).join(&amp;quot;\\&#039;&amp;quot;),&lt;br /&gt;
					l.newWin,&lt;br /&gt;
				]);&lt;br /&gt;
				title = popupString(&#039;lastContribHint&#039;);&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;sinceMe&#039;:&lt;br /&gt;
				onClick = simplePrintf(&amp;quot;pg.fn.getDiffSinceMyEdit(&#039;%s&#039;,%s)&amp;quot;, [&lt;br /&gt;
					l.article.toString(true).split(&#039;\\&#039;).join(&#039;\\\\&#039;).split(&amp;quot;&#039;&amp;quot;).join(&amp;quot;\\&#039;&amp;quot;),&lt;br /&gt;
					l.newWin,&lt;br /&gt;
				]);&lt;br /&gt;
				title = popupString(&#039;sinceMeHint&#039;);&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
		jsUrl = &#039;javascript:&#039; + onClick; // jshint ignore:line&lt;br /&gt;
		onClick += &#039;;return false;&#039;;&lt;br /&gt;
&lt;br /&gt;
		return generalNavLink({&lt;br /&gt;
			url: jsUrl,&lt;br /&gt;
			newWin: false, // can&#039;t have new windows with JS links, I think&lt;br /&gt;
			title: title,&lt;br /&gt;
			text: l.text,&lt;br /&gt;
			noPopup: l.noPopup,&lt;br /&gt;
			onclick: onClick,&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function popupMenuLink(l) {&lt;br /&gt;
		const jsUrl = simplePrintf(&#039;javascript:pg.fn.%s()&#039;, [l.id]); // jshint ignore:line&lt;br /&gt;
		const title = popupString(simplePrintf(&#039;%sHint&#039;, [l.id]));&lt;br /&gt;
		const onClick = simplePrintf(&#039;pg.fn.%s();return false;&#039;, [l.id]);&lt;br /&gt;
		return generalNavLink({&lt;br /&gt;
			url: jsUrl,&lt;br /&gt;
			newWin: false,&lt;br /&gt;
			title: title,&lt;br /&gt;
			text: l.text,&lt;br /&gt;
			noPopup: l.noPopup,&lt;br /&gt;
			onclick: onClick,&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function specialLink(l) {&lt;br /&gt;
		// properties: article, specialpage, text, sep&lt;br /&gt;
		if (typeof l.specialpage == &#039;undefined&#039; || !l.specialpage) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
		const base =&lt;br /&gt;
			pg.wiki.titlebase +&lt;br /&gt;
			mw.config.get(&#039;wgFormattedNamespaces&#039;)[pg.nsSpecialId] +&lt;br /&gt;
			&#039;:&#039; +&lt;br /&gt;
			l.specialpage;&lt;br /&gt;
		if (typeof l.sep == &#039;undefined&#039; || l.sep === null) {&lt;br /&gt;
			l.sep = &#039;&amp;amp;target=&#039;;&lt;br /&gt;
		}&lt;br /&gt;
		let article = l.article.urlString({&lt;br /&gt;
			keepSpaces: l.specialpage == &#039;Search&#039;,&lt;br /&gt;
		});&lt;br /&gt;
		let hint = popupString(l.specialpage + &#039;Hint&#039;);&lt;br /&gt;
		switch (l.specialpage) {&lt;br /&gt;
			case &#039;Log&#039;:&lt;br /&gt;
				switch (l.sep) {&lt;br /&gt;
					case &#039;&amp;amp;user=&#039;:&lt;br /&gt;
						hint = popupString(&#039;userLogHint&#039;);&lt;br /&gt;
						break;&lt;br /&gt;
					case &#039;&amp;amp;type=block&amp;amp;page=&#039;:&lt;br /&gt;
						hint = popupString(&#039;blockLogHint&#039;);&lt;br /&gt;
						break;&lt;br /&gt;
					case &#039;&amp;amp;page=&#039;:&lt;br /&gt;
						hint = popupString(&#039;pageLogHint&#039;);&lt;br /&gt;
						break;&lt;br /&gt;
					case &#039;&amp;amp;type=protect&amp;amp;page=&#039;:&lt;br /&gt;
						hint = popupString(&#039;protectLogHint&#039;);&lt;br /&gt;
						break;&lt;br /&gt;
					case &#039;&amp;amp;type=delete&amp;amp;page=&#039;:&lt;br /&gt;
						hint = popupString(&#039;deleteLogHint&#039;);&lt;br /&gt;
						break;&lt;br /&gt;
					default:&lt;br /&gt;
						log(&#039;Unknown log type, sep=&#039; + l.sep);&lt;br /&gt;
						hint = &#039;Missing hint (FIXME)&#039;;&lt;br /&gt;
				}&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;PrefixIndex&#039;:&lt;br /&gt;
				article += &#039;/&#039;;&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
		if (hint) {&lt;br /&gt;
			hint = simplePrintf(hint, [safeDecodeURI(l.article)]);&lt;br /&gt;
		} else {&lt;br /&gt;
			hint = safeDecodeURI(l.specialpage + &#039;:&#039; + l.article);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const url = base + l.sep + article;&lt;br /&gt;
		return generalNavLink({&lt;br /&gt;
			url: url,&lt;br /&gt;
			title: hint,&lt;br /&gt;
			text: l.text,&lt;br /&gt;
			newWin: l.newWin,&lt;br /&gt;
			noPopup: l.noPopup,&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Builds a link from a object representing a link&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param {Object} link&lt;br /&gt;
	 * @param {string} link.url URL&lt;br /&gt;
	 * @param {string} link.text The text to show for a link&lt;br /&gt;
	 * @param {string} link.title Title of the link, this shows up&lt;br /&gt;
	 * when you hover over the link&lt;br /&gt;
	 * @param {boolean} link.newWin Should open in a new Window&lt;br /&gt;
	 * @param {number} link.noPopup Should nest new popups from link (0 or 1)&lt;br /&gt;
	 * @param {string} link.onclick&lt;br /&gt;
	 * @return {string|null} null if no url is given&lt;br /&gt;
	 */&lt;br /&gt;
	function generalLink(link) {&lt;br /&gt;
		if (typeof link.url == &#039;undefined&#039;) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const elem = document.createElement( &#039;a&#039; );&lt;br /&gt;
&lt;br /&gt;
		elem.href = link.url;&lt;br /&gt;
		elem.title = link.title;&lt;br /&gt;
		// The onclick event adds raw JS in textual form to the HTML.&lt;br /&gt;
		// TODO: We should look into removing this, and/or auditing what gets sent.&lt;br /&gt;
		elem.setAttribute( &#039;onclick&#039;, link.onclick );&lt;br /&gt;
&lt;br /&gt;
		if ( link.noPopup ) {&lt;br /&gt;
			elem.setAttribute(&#039;noPopup&#039;, &#039;1&#039; );&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		let newWin;&lt;br /&gt;
		if (typeof link.newWin == &#039;undefined&#039; || link.newWin === null) {&lt;br /&gt;
			newWin = getValueOf(&#039;popupNewWindows&#039;);&lt;br /&gt;
		} else {&lt;br /&gt;
			newWin = link.newWin;&lt;br /&gt;
		}&lt;br /&gt;
		if (newWin) {&lt;br /&gt;
			elem.target = &#039;_blank&#039;;&lt;br /&gt;
		}&lt;br /&gt;
		if (link.className) {&lt;br /&gt;
			elem.className = link.className;&lt;br /&gt;
		}&lt;br /&gt;
		elem.innerText = pg.unescapeQuotesHTML(link.text);&lt;br /&gt;
&lt;br /&gt;
		return elem.outerHTML;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function appendParamsToLink(linkstr, params) {&lt;br /&gt;
		const sp = linkstr.parenSplit(/(href=&amp;quot;[^&amp;quot;]+?)&amp;quot;/i);&lt;br /&gt;
		if (sp.length &amp;lt; 2) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
		let ret = sp.shift() + sp.shift();&lt;br /&gt;
		ret += &#039;&amp;amp;&#039; + params + &#039;&amp;quot;&#039;;&lt;br /&gt;
		ret += sp.join(&#039;&#039;);&lt;br /&gt;
		return ret;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function changeLinkTargetLink(x) {&lt;br /&gt;
		// newTarget, text, hint, summary, clickButton, minor, title (optional), alsoChangeLabel {&lt;br /&gt;
		if (x.newTarget) {&lt;br /&gt;
			log(&#039;changeLinkTargetLink: newTarget=&#039; + x.newTarget);&lt;br /&gt;
		}&lt;br /&gt;
		if (x.oldTarget !== decodeURIComponent(x.oldTarget)) {&lt;br /&gt;
			log(&#039;This might be an input problem: &#039; + x.oldTarget);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// FIXME: first character of page title as well as namespace should be case insensitive&lt;br /&gt;
		// eg [[:category:X1]] and [[:Category:X1]] are equivalent&lt;br /&gt;
		// this&#039;ll break if charAt(0) is nasty&lt;br /&gt;
		const cA = mw.util.escapeRegExp(x.oldTarget);&lt;br /&gt;
		let chs = cA.charAt(0).toUpperCase();&lt;br /&gt;
		chs = &#039;[&#039; + chs + chs.toLowerCase() + &#039;]&#039;;&lt;br /&gt;
		let currentArticleRegexBit = chs + cA.substring(1);&lt;br /&gt;
		currentArticleRegexBit = currentArticleRegexBit&lt;br /&gt;
			.split(/(?:[_ ]+|%20)/g)&lt;br /&gt;
			.join(&#039;(?:[_ ]+|%20)&#039;)&lt;br /&gt;
			.split(&#039;\\(&#039;)&lt;br /&gt;
			.join(&#039;(?:%28|\\()&#039;)&lt;br /&gt;
			.split(&#039;\\)&#039;)&lt;br /&gt;
			.join(&#039;(?:%29|\\))&#039;); // why does this need to match encoded strings ? links in the document ?&lt;br /&gt;
		// leading and trailing space should be ignored, and anchor bits optional:&lt;br /&gt;
		currentArticleRegexBit = &#039;\\s*(&#039; + currentArticleRegexBit + &#039;(?:#[^\\[\\|]*)?)\\s*&#039;;&lt;br /&gt;
		// e.g. Computer (archaic) -&amp;gt; \s*([Cc]omputer[_ ](?:%2528|\()archaic(?:%2528|\)))\s*&lt;br /&gt;
&lt;br /&gt;
		// autoedit=s~\[\[([Cc]ad)\]\]~[[Computer-aided%20design|$1]]~g;s~\[\[([Cc]AD)[|]~[[Computer-aided%20design|~g&lt;br /&gt;
&lt;br /&gt;
		const title = x.title || mw.config.get(&#039;wgPageName&#039;).split(&#039;_&#039;).join(&#039; &#039;);&lt;br /&gt;
		const lk = titledWikiLink({&lt;br /&gt;
			article: new Title(title),&lt;br /&gt;
			newWin: x.newWin,&lt;br /&gt;
			action: &#039;edit&#039;,&lt;br /&gt;
			text: x.text,&lt;br /&gt;
			title: x.hint,&lt;br /&gt;
			className: &#039;popup_change_title_link&#039;,&lt;br /&gt;
		});&lt;br /&gt;
		let cmd = &#039;&#039;;&lt;br /&gt;
		if (x.newTarget) {&lt;br /&gt;
			// escape &#039;&amp;amp;&#039; and other nasties&lt;br /&gt;
			const t = x.newTarget;&lt;br /&gt;
			const s = mw.util.escapeRegExp(x.newTarget);&lt;br /&gt;
			if (x.alsoChangeLabel) {&lt;br /&gt;
				cmd += &#039;s~\\[\\[&#039; + currentArticleRegexBit + &#039;\\]\\]~[[&#039; + t + &#039;]]~g;&#039;;&lt;br /&gt;
				cmd += &#039;s~\\[\\[&#039; + currentArticleRegexBit + &#039;[|]~[[&#039; + t + &#039;|~g;&#039;;&lt;br /&gt;
				cmd += &#039;s~\\[\\[&#039; + s + &#039;\\|&#039; + s + &#039;\\]\\]~[[&#039; + t + &#039;]]~g&#039;;&lt;br /&gt;
			} else {&lt;br /&gt;
				cmd += &#039;s~\\[\\[&#039; + currentArticleRegexBit + &#039;\\]\\]~[[&#039; + t + &#039;|$1]]~g;&#039;;&lt;br /&gt;
				cmd += &#039;s~\\[\\[&#039; + currentArticleRegexBit + &#039;[|]~[[&#039; + t + &#039;|~g;&#039;;&lt;br /&gt;
				cmd += &#039;s~\\[\\[&#039; + s + &#039;\\|&#039; + s + &#039;\\]\\]~[[&#039; + t + &#039;]]~g&#039;;&lt;br /&gt;
			}&lt;br /&gt;
		} else {&lt;br /&gt;
			cmd += &#039;s~\\[\\[&#039; + currentArticleRegexBit + &#039;\\]\\]~$1~g;&#039;;&lt;br /&gt;
			cmd += &#039;s~\\[\\[&#039; + currentArticleRegexBit + &#039;[|](.*?)\\]\\]~$2~g&#039;;&lt;br /&gt;
		}&lt;br /&gt;
		// Build query&lt;br /&gt;
		cmd = &#039;autoedit=&#039; + encodeURIComponent(cmd);&lt;br /&gt;
		cmd +=&lt;br /&gt;
			&#039;&amp;amp;autoclick=&#039; +&lt;br /&gt;
			encodeURIComponent(x.clickButton) +&lt;br /&gt;
			&#039;&amp;amp;actoken=&#039; +&lt;br /&gt;
			encodeURIComponent(autoClickToken());&lt;br /&gt;
		cmd += x.minor === null ? &#039;&#039; : &#039;&amp;amp;autominor=&#039; + encodeURIComponent(x.minor);&lt;br /&gt;
		cmd += x.watch === null ? &#039;&#039; : &#039;&amp;amp;autowatch=&#039; + encodeURIComponent(x.watch);&lt;br /&gt;
		cmd += &#039;&amp;amp;autosummary=&#039; + encodeURIComponent(x.summary);&lt;br /&gt;
		cmd += &#039;&amp;amp;autoimpl=&#039; + encodeURIComponent(popupString(&#039;autoedit_version&#039;));&lt;br /&gt;
		return appendParamsToLink(lk, cmd);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function redirLink(redirMatch, article) {&lt;br /&gt;
		// NB redirMatch is in wikiText&lt;br /&gt;
		let ret = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
		if (getValueOf(&#039;popupAppendRedirNavLinks&#039;) &amp;amp;&amp;amp; getValueOf(&#039;popupNavLinks&#039;)) {&lt;br /&gt;
			ret += &#039;&amp;lt;hr /&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
			if (getValueOf(&#039;popupFixRedirs&#039;) &amp;amp;&amp;amp; typeof autoEdit != &#039;undefined&#039; &amp;amp;&amp;amp; autoEdit) {&lt;br /&gt;
				ret += popupString(&#039;Redirects to: (Fix &#039;);&lt;br /&gt;
				log(&#039;redirLink: newTarget=&#039; + redirMatch);&lt;br /&gt;
				ret += addPopupShortcut(&lt;br /&gt;
					changeLinkTargetLink({&lt;br /&gt;
						newTarget: redirMatch,&lt;br /&gt;
						text: popupString(&#039;target&#039;),&lt;br /&gt;
						hint: popupString(&#039;Fix this redirect, changing just the link target&#039;),&lt;br /&gt;
						summary: simplePrintf(getValueOf(&#039;popupFixRedirsSummary&#039;), [&lt;br /&gt;
							article.toString(),&lt;br /&gt;
							redirMatch,&lt;br /&gt;
						]),&lt;br /&gt;
						oldTarget: article.toString(),&lt;br /&gt;
						clickButton: getValueOf(&#039;popupRedirAutoClick&#039;),&lt;br /&gt;
						minor: true,&lt;br /&gt;
						watch: getValueOf(&#039;popupWatchRedirredPages&#039;),&lt;br /&gt;
					}),&lt;br /&gt;
					&#039;R&#039;&lt;br /&gt;
				);&lt;br /&gt;
				ret += popupString(&#039; or &#039;);&lt;br /&gt;
				ret += addPopupShortcut(&lt;br /&gt;
					changeLinkTargetLink({&lt;br /&gt;
						newTarget: redirMatch,&lt;br /&gt;
						text: popupString(&#039;target &amp;amp; label&#039;),&lt;br /&gt;
						hint: popupString(&#039;Fix this redirect, changing the link target and label&#039;),&lt;br /&gt;
						summary: simplePrintf(getValueOf(&#039;popupFixRedirsSummary&#039;), [&lt;br /&gt;
							article.toString(),&lt;br /&gt;
							redirMatch,&lt;br /&gt;
						]),&lt;br /&gt;
						oldTarget: article.toString(),&lt;br /&gt;
						clickButton: getValueOf(&#039;popupRedirAutoClick&#039;),&lt;br /&gt;
						minor: true,&lt;br /&gt;
						watch: getValueOf(&#039;popupWatchRedirredPages&#039;),&lt;br /&gt;
						alsoChangeLabel: true,&lt;br /&gt;
					}),&lt;br /&gt;
					&#039;R&#039;&lt;br /&gt;
				);&lt;br /&gt;
				ret += popupString(&#039;)&#039;);&lt;br /&gt;
			} else {&lt;br /&gt;
				ret += popupString(&#039;Redirects&#039;) + popupString(&#039; to &#039;);&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			return ret;&lt;br /&gt;
		} else {&lt;br /&gt;
			return (&lt;br /&gt;
				&#039;&amp;lt;br&amp;gt; &#039; +&lt;br /&gt;
				popupString(&#039;Redirects&#039;) +&lt;br /&gt;
				popupString(&#039; to &#039;) +&lt;br /&gt;
				titledWikiLink({&lt;br /&gt;
					article: new Title().fromWikiText(redirMatch),&lt;br /&gt;
					action: &#039;view&#039; /* FIXME: newWin */,&lt;br /&gt;
					text: safeDecodeURI(redirMatch),&lt;br /&gt;
					title: popupString(&#039;Bypass redirect&#039;),&lt;br /&gt;
				})&lt;br /&gt;
			);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function arinLink(l) {&lt;br /&gt;
		if (!saneLinkCheck(l)) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
		if (!l.article.isIpUser() || !pg.wiki.wikimedia) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const uN = l.article.userName();&lt;br /&gt;
&lt;br /&gt;
		return generalNavLink({&lt;br /&gt;
			url: &#039;http://ws.arin.net/cgi-bin/whois.pl?queryinput=&#039; + encodeURIComponent(uN),&lt;br /&gt;
			newWin: l.newWin,&lt;br /&gt;
			title: tprintf(&#039;Look up %s in ARIN whois database&#039;, [uN]),&lt;br /&gt;
			text: l.text,&lt;br /&gt;
			noPopup: 1,&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function toolDbName(cookieStyle) {&lt;br /&gt;
		let ret = mw.config.get(&#039;wgDBname&#039;);&lt;br /&gt;
		if (!cookieStyle) {&lt;br /&gt;
			ret += &#039;_p&#039;;&lt;br /&gt;
		}&lt;br /&gt;
		return ret;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function saneLinkCheck(l) {&lt;br /&gt;
		if (typeof l.article != typeof {} || typeof l.text != typeof &#039;&#039;) {&lt;br /&gt;
			return false;&lt;br /&gt;
		}&lt;br /&gt;
		return true;&lt;br /&gt;
	}&lt;br /&gt;
	function editCounterLink(l) {&lt;br /&gt;
		if (!saneLinkCheck(l)) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
		if (!pg.wiki.wikimedia) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
		const uN = l.article.userName();&lt;br /&gt;
		const tool = getValueOf(&#039;popupEditCounterTool&#039;);&lt;br /&gt;
		let url;&lt;br /&gt;
		const defaultToolUrl = &#039;https://xtools.wmflabs.org/ec?user=$1&amp;amp;project=$2.$3&amp;amp;uselang=&#039; + mw.config.get(&#039;wgUserLanguage&#039;);&lt;br /&gt;
&lt;br /&gt;
		switch (tool) {&lt;br /&gt;
			case &#039;custom&#039;:&lt;br /&gt;
				url = simplePrintf(getValueOf(&#039;popupEditCounterUrl&#039;), [&lt;br /&gt;
					encodeURIComponent(uN),&lt;br /&gt;
					toolDbName(),&lt;br /&gt;
				]);&lt;br /&gt;
				break;&lt;br /&gt;
			case &#039;soxred&#039;: // no longer available&lt;br /&gt;
			case &#039;kate&#039;: // no longer available&lt;br /&gt;
			case &#039;interiot&#039;: // no longer available&lt;br /&gt;
			/* fall through */&lt;br /&gt;
			case &#039;supercount&#039;:&lt;br /&gt;
			default:&lt;br /&gt;
				var theWiki = pg.wiki.hostname.split(&#039;.&#039;);&lt;br /&gt;
				url = simplePrintf(defaultToolUrl, [encodeURIComponent(uN), theWiki[0], theWiki[1]]);&lt;br /&gt;
		}&lt;br /&gt;
		return generalNavLink({&lt;br /&gt;
			url: url,&lt;br /&gt;
			title: tprintf(&#039;editCounterLinkHint&#039;, [uN]),&lt;br /&gt;
			newWin: l.newWin,&lt;br /&gt;
			text: l.text,&lt;br /&gt;
			noPopup: 1,&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function globalSearchLink(l) {&lt;br /&gt;
		if (!saneLinkCheck(l)) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const base = &#039;https://global-search.toolforge.org/?uselang=&#039; + mw.config.get(&#039;wgUserLanguage&#039;) + &#039;&amp;amp;q=&#039;;&lt;br /&gt;
		const article = l.article.urlString({ keepSpaces: true });&lt;br /&gt;
&lt;br /&gt;
		return generalNavLink({&lt;br /&gt;
			url: base + article,&lt;br /&gt;
			newWin: l.newWin,&lt;br /&gt;
			title: tprintf(&#039;globalSearchHint&#039;, [safeDecodeURI(l.article)]),&lt;br /&gt;
			text: l.text,&lt;br /&gt;
			noPopup: 1,&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function googleLink(l) {&lt;br /&gt;
		if (!saneLinkCheck(l)) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		const base = &#039;https://www.google.com/search?q=&#039;;&lt;br /&gt;
		const article = l.article.urlString({ keepSpaces: true });&lt;br /&gt;
&lt;br /&gt;
		return generalNavLink({&lt;br /&gt;
			url: base + &#039;%22&#039; + article + &#039;%22&#039;,&lt;br /&gt;
			newWin: l.newWin,&lt;br /&gt;
			title: tprintf(&#039;googleSearchHint&#039;, [safeDecodeURI(l.article)]),&lt;br /&gt;
			text: l.text,&lt;br /&gt;
			noPopup: 1,&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function editorListLink(l) {&lt;br /&gt;
		if (!saneLinkCheck(l)) {&lt;br /&gt;
			return null;&lt;br /&gt;
		}&lt;br /&gt;
		const article = l.article.articleFromTalkPage() || l.article;&lt;br /&gt;
		const url =&lt;br /&gt;
			&#039;https://xtools.wmflabs.org/articleinfo/&#039; +&lt;br /&gt;
			encodeURI(pg.wiki.hostname) +&lt;br /&gt;
			&#039;/&#039; +&lt;br /&gt;
			article.urlString() +&lt;br /&gt;
			&#039;?uselang=&#039; +&lt;br /&gt;
			mw.config.get(&#039;wgUserLanguage&#039;);&lt;br /&gt;
		return generalNavLink({&lt;br /&gt;
			url: url,&lt;br /&gt;
			title: tprintf(&#039;editorListHint&#039;, [article]),&lt;br /&gt;
			newWin: l.newWin,&lt;br /&gt;
			text: l.text,&lt;br /&gt;
			noPopup: 1,&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function generalNavLink(l) {&lt;br /&gt;
		l.className = l.className === null ? &#039;popupNavLink&#039; : l.className;&lt;br /&gt;
		return generalLink(l);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	//////////////////////////////////////////////////&lt;br /&gt;
	// magic history links&lt;br /&gt;
	//&lt;br /&gt;
&lt;br /&gt;
	function getHistoryInfo(wikipage, whatNext) {&lt;br /&gt;
		log(&#039;getHistoryInfo&#039;);&lt;br /&gt;
		getHistory(&lt;br /&gt;
			wikipage,&lt;br /&gt;
			whatNext ?&lt;br /&gt;
				(d) =&amp;gt; {&lt;br /&gt;
					whatNext(processHistory(d));&lt;br /&gt;
				} :&lt;br /&gt;
				processHistory&lt;br /&gt;
		);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// FIXME eliminate pg.idNumber ... how? :-(&lt;br /&gt;
&lt;br /&gt;
	function getHistory(wikipage, onComplete) {&lt;br /&gt;
		log(&#039;getHistory&#039;);&lt;br /&gt;
		const url =&lt;br /&gt;
			pg.wiki.apiwikibase +&lt;br /&gt;
			&#039;?format=json&amp;amp;formatversion=2&amp;amp;action=query&amp;amp;prop=revisions&amp;amp;titles=&#039; +&lt;br /&gt;
			new Title(wikipage).urlString() +&lt;br /&gt;
			&#039;&amp;amp;rvlimit=&#039; +&lt;br /&gt;
			getValueOf(&#039;popupHistoryLimit&#039;);&lt;br /&gt;
		log(&#039;getHistory: url=&#039; + url);&lt;br /&gt;
		return startDownload(url, pg.idNumber + &#039;history&#039;, onComplete);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function processHistory(download) {&lt;br /&gt;
		const jsobj = getJsObj(download.data);&lt;br /&gt;
		try {&lt;br /&gt;
			const revisions = anyChild(jsobj.query.pages).revisions;&lt;br /&gt;
			const edits = [];&lt;br /&gt;
			for (let i = 0; i &amp;lt; revisions.length; ++i) {&lt;br /&gt;
				edits.push({ oldid: revisions[i].revid, editor: revisions[i].user });&lt;br /&gt;
			}&lt;br /&gt;
			log(&#039;processed &#039; + edits.length + &#039; edits&#039;);&lt;br /&gt;
			return finishProcessHistory(edits, mw.config.get(&#039;wgUserName&#039;));&lt;br /&gt;
		} catch (someError) {&lt;br /&gt;
			log(&#039;Something went wrong with JSON business&#039;);&lt;br /&gt;
			return finishProcessHistory([]);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function finishProcessHistory(edits, userName) {&lt;br /&gt;
		const histInfo = {};&lt;br /&gt;
&lt;br /&gt;
		histInfo.edits = edits;&lt;br /&gt;
		histInfo.userName = userName;&lt;br /&gt;
&lt;br /&gt;
		for (let i = 0; i &amp;lt; edits.length; ++i) {&lt;br /&gt;
			if (typeof histInfo.myLastEdit === &#039;undefined&#039; &amp;amp;&amp;amp; userName &amp;amp;&amp;amp; edits[i].editor == userName) {&lt;br /&gt;
				histInfo.myLastEdit = {&lt;br /&gt;
					index: i,&lt;br /&gt;
					oldid: edits[i].oldid,&lt;br /&gt;
					previd: i === 0 ? null : edits[i - 1].oldid,&lt;br /&gt;
				};&lt;br /&gt;
			}&lt;br /&gt;
			if (typeof histInfo.firstNewEditor === &#039;undefined&#039; &amp;amp;&amp;amp; edits[i].editor != edits[0].editor) {&lt;br /&gt;
				histInfo.firstNewEditor = {&lt;br /&gt;
					index: i,&lt;br /&gt;
					oldid: edits[i].oldid,&lt;br /&gt;
					previd: i === 0 ? null : edits[i - 1].oldid,&lt;br /&gt;
				};&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		//pg.misc.historyInfo=histInfo;&lt;br /&gt;
		return histInfo;&lt;br /&gt;
	}&lt;br /&gt;
	// ENDFILE: links.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: options.js&lt;br /&gt;
	//////////////////////////////////////////////////&lt;br /&gt;
	// options&lt;br /&gt;
&lt;br /&gt;
	// check for existing value, else use default&lt;br /&gt;
	function defaultize(x) {&lt;br /&gt;
		if (pg.option[x] === null || typeof pg.option[x] == &#039;undefined&#039;) {&lt;br /&gt;
			if (typeof window[x] != &#039;undefined&#039;) {&lt;br /&gt;
				pg.option[x] = window[x];&lt;br /&gt;
			} else {&lt;br /&gt;
				pg.option[x] = pg.optionDefault[x];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function newOption(x, def) {&lt;br /&gt;
		pg.optionDefault[x] = def;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function setDefault(x, def) {&lt;br /&gt;
		return newOption(x, def);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function getValueOf(varName) {&lt;br /&gt;
		defaultize(varName);&lt;br /&gt;
		return pg.option[varName];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/*eslint-disable */&lt;br /&gt;
	function useDefaultOptions() {&lt;br /&gt;
		// for testing&lt;br /&gt;
		for (var p in pg.optionDefault) {&lt;br /&gt;
			pg.option[p] = pg.optionDefault[p];&lt;br /&gt;
			if (typeof window[p] != &#039;undefined&#039;) {&lt;br /&gt;
				delete window[p];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	/*eslint-enable */&lt;br /&gt;
&lt;br /&gt;
	function setOptions() {&lt;br /&gt;
		// user-settable parameters and defaults&lt;br /&gt;
		let userIsSysop = false;&lt;br /&gt;
		if (mw.config.get(&#039;wgUserGroups&#039;)) {&lt;br /&gt;
			for (let g = 0; g &amp;lt; mw.config.get(&#039;wgUserGroups&#039;).length; ++g) {&lt;br /&gt;
				if (mw.config.get(&#039;wgUserGroups&#039;)[g] == &#039;sysop&#039;) {&lt;br /&gt;
					userIsSysop = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Basic options&lt;br /&gt;
		newOption(&#039;popupDelay&#039;, 0.5);&lt;br /&gt;
		newOption(&#039;popupHideDelay&#039;, 0.5);&lt;br /&gt;
		newOption(&#039;simplePopups&#039;, false);&lt;br /&gt;
		newOption(&#039;popupStructure&#039;, &#039;shortmenus&#039;); // see later - default for popupStructure is &#039;original&#039; if simplePopups is true&lt;br /&gt;
		newOption(&#039;popupActionsMenu&#039;, true);&lt;br /&gt;
		newOption(&#039;popupSetupMenu&#039;, true);&lt;br /&gt;
		newOption(&#039;popupAdminLinks&#039;, userIsSysop);&lt;br /&gt;
		newOption(&#039;popupShortcutKeys&#039;, false);&lt;br /&gt;
		newOption(&#039;popupHistoricalLinks&#039;, true);&lt;br /&gt;
		newOption(&#039;popupOnlyArticleLinks&#039;, true);&lt;br /&gt;
		newOption(&#039;removeTitles&#039;, true);&lt;br /&gt;
		newOption(&#039;popupMaxWidth&#039;, 350);&lt;br /&gt;
		newOption(&#039;popupSimplifyMainLink&#039;, true);&lt;br /&gt;
		newOption(&#039;popupAppendRedirNavLinks&#039;, true);&lt;br /&gt;
		newOption(&#039;popupTocLinks&#039;, false);&lt;br /&gt;
		newOption(&#039;popupSubpopups&#039;, true);&lt;br /&gt;
		newOption(&#039;popupDragHandle&#039;, false /* &#039;popupTopLinks&#039;*/);&lt;br /&gt;
		newOption(&#039;popupLazyPreviews&#039;, true);&lt;br /&gt;
		newOption(&#039;popupLazyDownloads&#039;, true);&lt;br /&gt;
		newOption(&#039;popupAllDabsStubs&#039;, false);&lt;br /&gt;
		newOption(&#039;popupDebugging&#039;, false);&lt;br /&gt;
		newOption(&#039;popupActiveNavlinks&#039;, true);&lt;br /&gt;
		newOption(&#039;popupModifier&#039;, false); // ctrl, shift, alt or meta&lt;br /&gt;
		newOption(&#039;popupModifierAction&#039;, &#039;enable&#039;); // or &#039;disable&#039;&lt;br /&gt;
		newOption(&#039;popupDraggable&#039;, true);&lt;br /&gt;
		newOption(&#039;popupReview&#039;, false);&lt;br /&gt;
		newOption(&#039;popupLocale&#039;, false);&lt;br /&gt;
		newOption(&#039;popupDateTimeFormatterOptions&#039;, {&lt;br /&gt;
			year: &#039;numeric&#039;,&lt;br /&gt;
			month: &#039;long&#039;,&lt;br /&gt;
			day: &#039;numeric&#039;,&lt;br /&gt;
			hour12: false,&lt;br /&gt;
			hour: &#039;2-digit&#039;,&lt;br /&gt;
			minute: &#039;2-digit&#039;,&lt;br /&gt;
			second: &#039;2-digit&#039;,&lt;br /&gt;
		});&lt;br /&gt;
		newOption(&#039;popupDateFormatterOptions&#039;, {&lt;br /&gt;
			year: &#039;numeric&#039;,&lt;br /&gt;
			month: &#039;long&#039;,&lt;br /&gt;
			day: &#039;numeric&#039;,&lt;br /&gt;
		});&lt;br /&gt;
		newOption(&#039;popupTimeFormatterOptions&#039;, {&lt;br /&gt;
			hour12: false,&lt;br /&gt;
			hour: &#039;2-digit&#039;,&lt;br /&gt;
			minute: &#039;2-digit&#039;,&lt;br /&gt;
			second: &#039;2-digit&#039;,&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		// images&lt;br /&gt;
		newOption(&#039;popupImages&#039;, true);&lt;br /&gt;
		newOption(&#039;imagePopupsForImages&#039;, true);&lt;br /&gt;
		newOption(&#039;popupNeverGetThumbs&#039;, false);&lt;br /&gt;
		//newOption(&#039;popupImagesToggleSize&#039;,       true);&lt;br /&gt;
		newOption(&#039;popupThumbAction&#039;, &#039;imagepage&#039;); //&#039;sizetoggle&#039;);&lt;br /&gt;
		newOption(&#039;popupImageSize&#039;, 60);&lt;br /&gt;
		newOption(&#039;popupImageSizeLarge&#039;, 200);&lt;br /&gt;
&lt;br /&gt;
		// redirs, dabs, reversion&lt;br /&gt;
		newOption(&#039;popupFixRedirs&#039;, false);&lt;br /&gt;
		newOption(&#039;popupRedirAutoClick&#039;, &#039;wpDiff&#039;);&lt;br /&gt;
		newOption(&#039;popupFixDabs&#039;, false);&lt;br /&gt;
		newOption(&#039;popupDabsAutoClick&#039;, &#039;wpDiff&#039;);&lt;br /&gt;
		newOption(&#039;popupRevertSummaryPrompt&#039;, false);&lt;br /&gt;
		newOption(&#039;popupMinorReverts&#039;, false);&lt;br /&gt;
		newOption(&#039;popupRedlinkRemoval&#039;, false);&lt;br /&gt;
		newOption(&#039;popupRedlinkAutoClick&#039;, &#039;wpDiff&#039;);&lt;br /&gt;
		newOption(&#039;popupWatchDisambiggedPages&#039;, null);&lt;br /&gt;
		newOption(&#039;popupWatchRedirredPages&#039;, null);&lt;br /&gt;
		newOption(&#039;popupDabWiktionary&#039;, &#039;last&#039;);&lt;br /&gt;
&lt;br /&gt;
		// navlinks&lt;br /&gt;
		newOption(&#039;popupNavLinks&#039;, true);&lt;br /&gt;
		newOption(&#039;popupNavLinkSeparator&#039;, &#039; &amp;amp;sdot; &#039;);&lt;br /&gt;
		newOption(&#039;popupLastEditLink&#039;, true);&lt;br /&gt;
		newOption(&#039;popupEditCounterTool&#039;, &#039;supercount&#039;);&lt;br /&gt;
		newOption(&#039;popupEditCounterUrl&#039;, &#039;&#039;);&lt;br /&gt;
&lt;br /&gt;
		// previews etc&lt;br /&gt;
		newOption(&#039;popupPreviews&#039;, true);&lt;br /&gt;
		newOption(&#039;popupSummaryData&#039;, true);&lt;br /&gt;
		newOption(&#039;popupMaxPreviewSentences&#039;, 5);&lt;br /&gt;
		newOption(&#039;popupMaxPreviewCharacters&#039;, 600);&lt;br /&gt;
		newOption(&#039;popupLastModified&#039;, true);&lt;br /&gt;
		newOption(&#039;popupPreviewKillTemplates&#039;, true);&lt;br /&gt;
		newOption(&#039;popupPreviewRawTemplates&#039;, true);&lt;br /&gt;
		newOption(&#039;popupPreviewFirstParOnly&#039;, true);&lt;br /&gt;
		newOption(&#039;popupPreviewCutHeadings&#039;, true);&lt;br /&gt;
		newOption(&#039;popupPreviewButton&#039;, false);&lt;br /&gt;
		newOption(&#039;popupPreviewButtonEvent&#039;, &#039;click&#039;);&lt;br /&gt;
&lt;br /&gt;
		// diffs&lt;br /&gt;
		newOption(&#039;popupPreviewDiffs&#039;, true);&lt;br /&gt;
		newOption(&#039;popupDiffMaxLines&#039;, 100);&lt;br /&gt;
		newOption(&#039;popupDiffContextLines&#039;, 2);&lt;br /&gt;
		newOption(&#039;popupDiffContextCharacters&#039;, 40);&lt;br /&gt;
		newOption(&#039;popupDiffDates&#039;, true);&lt;br /&gt;
		newOption(&#039;popupDiffDatePrinter&#039;, &#039;toLocaleString&#039;); // no longer in use&lt;br /&gt;
&lt;br /&gt;
		// edit summaries. God, these are ugly.&lt;br /&gt;
		newOption(&#039;popupReviewedSummary&#039;, popupString(&#039;defaultpopupReviewedSummary&#039;));&lt;br /&gt;
		newOption(&#039;popupFixDabsSummary&#039;, popupString(&#039;defaultpopupFixDabsSummary&#039;));&lt;br /&gt;
		newOption(&#039;popupExtendedRevertSummary&#039;, popupString(&#039;defaultpopupExtendedRevertSummary&#039;));&lt;br /&gt;
		newOption(&#039;popupRevertSummary&#039;, popupString(&#039;defaultpopupRevertSummary&#039;));&lt;br /&gt;
		newOption(&#039;popupRevertToPreviousSummary&#039;, popupString(&#039;defaultpopupRevertToPreviousSummary&#039;));&lt;br /&gt;
		newOption(&#039;popupQueriedRevertSummary&#039;, popupString(&#039;defaultpopupQueriedRevertSummary&#039;));&lt;br /&gt;
		newOption(&lt;br /&gt;
			&#039;popupQueriedRevertToPreviousSummary&#039;,&lt;br /&gt;
			popupString(&#039;defaultpopupQueriedRevertToPreviousSummary&#039;)&lt;br /&gt;
		);&lt;br /&gt;
		newOption(&#039;popupFixRedirsSummary&#039;, popupString(&#039;defaultpopupFixRedirsSummary&#039;));&lt;br /&gt;
		newOption(&#039;popupRedlinkSummary&#039;, popupString(&#039;defaultpopupRedlinkSummary&#039;));&lt;br /&gt;
		newOption(&#039;popupRmDabLinkSummary&#039;, popupString(&#039;defaultpopupRmDabLinkSummary&#039;));&lt;br /&gt;
		// misc&lt;br /&gt;
		newOption(&#039;popupHistoryLimit&#039;, 50);&lt;br /&gt;
		newOption(&#039;popupFilters&#039;, [&lt;br /&gt;
			popupFilterStubDetect,&lt;br /&gt;
			popupFilterDisambigDetect,&lt;br /&gt;
			popupFilterPageSize,&lt;br /&gt;
			popupFilterCountLinks,&lt;br /&gt;
			popupFilterCountImages,&lt;br /&gt;
			popupFilterCountCategories,&lt;br /&gt;
			popupFilterLastModified,&lt;br /&gt;
			popupFilterWikibaseItem,&lt;br /&gt;
		]);&lt;br /&gt;
		newOption(&#039;extraPopupFilters&#039;, []);&lt;br /&gt;
		newOption(&#039;popupOnEditSelection&#039;, &#039;cursor&#039;);&lt;br /&gt;
		newOption(&#039;popupPreviewHistory&#039;, true);&lt;br /&gt;
		newOption(&#039;popupImageLinks&#039;, true);&lt;br /&gt;
		newOption(&#039;popupCategoryMembers&#039;, true);&lt;br /&gt;
		newOption(&#039;popupUserInfo&#039;, true);&lt;br /&gt;
		newOption(&#039;popupHistoryPreviewLimit&#039;, 25);&lt;br /&gt;
		newOption(&#039;popupContribsPreviewLimit&#039;, 25);&lt;br /&gt;
		newOption(&#039;popupRevDelUrl&#039;, &#039;//en.wikipedia.org/wiki/Wikipedia:Revision_deletion&#039;);&lt;br /&gt;
		newOption(&#039;popupShowGender&#039;, true);&lt;br /&gt;
&lt;br /&gt;
		// new windows&lt;br /&gt;
		newOption(&#039;popupNewWindows&#039;, false);&lt;br /&gt;
		newOption(&#039;popupLinksNewWindow&#039;, { lastContrib: true, sinceMe: true });&lt;br /&gt;
&lt;br /&gt;
		// regexps&lt;br /&gt;
		newOption(&lt;br /&gt;
			&#039;popupDabRegexp&#039;,&lt;br /&gt;
			&#039;disambiguation\\}\\}|\\{\\{\\s*(d(ab|isamb(ig(uation)?)?)|(((geo|hn|road?|school|number)dis)|[234][lc][acw]|(road|ship)index))\\s*(\\|[^}]*)?\\}\\}|is a .*disambiguation.*page&#039;&lt;br /&gt;
		);&lt;br /&gt;
		newOption(&#039;popupAnchorRegexp&#039;, &#039;anchors?&#039;); //how to identify an anchors template&lt;br /&gt;
		newOption(&#039;popupStubRegexp&#039;, &#039;(sect)?stub[}][}]|This .*-related article is a .*stub&#039;);&lt;br /&gt;
		newOption(&lt;br /&gt;
			&#039;popupImageVarsRegexp&#039;,&lt;br /&gt;
			&#039;image|image_(?:file|skyline|name|flag|seal)|cover|badge|logo&#039;&lt;br /&gt;
		);&lt;br /&gt;
	}&lt;br /&gt;
	// ENDFILE: options.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: strings.js&lt;br /&gt;
	//////////////////////////////////////////////////&lt;br /&gt;
	// Translatable strings&lt;br /&gt;
	//////////////////////////////////////////////////&lt;br /&gt;
	//&lt;br /&gt;
	// See instructions at&lt;br /&gt;
	// https://en.wikipedia.org/wiki/Wikipedia:Tools/Navigation_popups/Translation&lt;br /&gt;
&lt;br /&gt;
	pg.string = {&lt;br /&gt;
		/////////////////////////////////////&lt;br /&gt;
		// summary data, searching etc.&lt;br /&gt;
		/////////////////////////////////////&lt;br /&gt;
		article: &#039;article&#039;,&lt;br /&gt;
		category: &#039;category&#039;,&lt;br /&gt;
		categories: &#039;categories&#039;,&lt;br /&gt;
		image: &#039;image&#039;,&lt;br /&gt;
		images: &#039;images&#039;,&lt;br /&gt;
		stub: &#039;stub&#039;,&lt;br /&gt;
		&#039;section stub&#039;: &#039;section stub&#039;,&lt;br /&gt;
		&#039;Empty page&#039;: &#039;Empty page&#039;,&lt;br /&gt;
		kB: &#039;kB&#039;,&lt;br /&gt;
		bytes: &#039;bytes&#039;,&lt;br /&gt;
		day: &#039;day&#039;,&lt;br /&gt;
		days: &#039;days&#039;,&lt;br /&gt;
		hour: &#039;hour&#039;,&lt;br /&gt;
		hours: &#039;hours&#039;,&lt;br /&gt;
		minute: &#039;minute&#039;,&lt;br /&gt;
		minutes: &#039;minutes&#039;,&lt;br /&gt;
		second: &#039;second&#039;,&lt;br /&gt;
		seconds: &#039;seconds&#039;,&lt;br /&gt;
		week: &#039;week&#039;,&lt;br /&gt;
		weeks: &#039;weeks&#039;,&lt;br /&gt;
		search: &#039;search&#039;,&lt;br /&gt;
		SearchHint: &#039;Find English Wikipedia articles containing %s&#039;,&lt;br /&gt;
		web: &#039;web&#039;,&lt;br /&gt;
		global: &#039;global&#039;,&lt;br /&gt;
		globalSearchHint: &#039;Search across Wikipedias in different languages for %s&#039;,&lt;br /&gt;
		googleSearchHint: &#039;Google for %s&#039;,&lt;br /&gt;
		/////////////////////////////////////&lt;br /&gt;
		// article-related actions and info&lt;br /&gt;
		// (some actions also apply to user pages)&lt;br /&gt;
		/////////////////////////////////////&lt;br /&gt;
		actions: &#039;actions&#039;, ///// view articles and view talk&lt;br /&gt;
		popupsMenu: &#039;popups&#039;,&lt;br /&gt;
		togglePreviewsHint: &#039;Toggle preview generation in popups on this page&#039;,&lt;br /&gt;
		&#039;enable previews&#039;: &#039;enable previews&#039;,&lt;br /&gt;
		&#039;disable previews&#039;: &#039;disable previews&#039;,&lt;br /&gt;
		&#039;toggle previews&#039;: &#039;toggle previews&#039;,&lt;br /&gt;
		&#039;show preview&#039;: &#039;show preview&#039;,&lt;br /&gt;
		reset: &#039;reset&#039;,&lt;br /&gt;
		&#039;more...&#039;: &#039;more...&#039;,&lt;br /&gt;
		disable: &#039;disable popups&#039;,&lt;br /&gt;
		disablePopupsHint: &#039;Disable popups on this page. Reload page to re-enable.&#039;,&lt;br /&gt;
		historyfeedHint: &#039;RSS feed of recent changes to this page&#039;,&lt;br /&gt;
		purgePopupsHint: &#039;Reset popups, clearing all cached popup data.&#039;,&lt;br /&gt;
		PopupsHint: &#039;Reset popups, clearing all cached popup data.&#039;,&lt;br /&gt;
		spacebar: &#039;space&#039;,&lt;br /&gt;
		view: &#039;view&#039;,&lt;br /&gt;
		&#039;view article&#039;: &#039;view article&#039;,&lt;br /&gt;
		viewHint: &#039;Go to %s&#039;,&lt;br /&gt;
		talk: &#039;talk&#039;,&lt;br /&gt;
		&#039;talk page&#039;: &#039;talk page&#039;,&lt;br /&gt;
		&#039;this&amp;amp;nbsp;revision&#039;: &#039;this&amp;amp;nbsp;revision&#039;,&lt;br /&gt;
		&#039;revision %s of %s&#039;: &#039;revision %s of %s&#039;,&lt;br /&gt;
		&#039;Revision %s of %s&#039;: &#039;Revision %s of %s&#039;,&lt;br /&gt;
		&#039;the revision prior to revision %s of %s&#039;: &#039;the revision prior to revision %s of %s&#039;,&lt;br /&gt;
		&#039;Toggle image size&#039;: &#039;Click to toggle image size&#039;,&lt;br /&gt;
		del: &#039;del&#039;, ///// delete, protect, move&lt;br /&gt;
		delete: &#039;delete&#039;,&lt;br /&gt;
		deleteHint: &#039;Delete %s&#039;,&lt;br /&gt;
		undeleteShort: &#039;un&#039;,&lt;br /&gt;
		UndeleteHint: &#039;Show the deletion history for %s&#039;,&lt;br /&gt;
		protect: &#039;protect&#039;,&lt;br /&gt;
		protectHint: &#039;Restrict editing rights to %s&#039;,&lt;br /&gt;
		unprotectShort: &#039;un&#039;,&lt;br /&gt;
		unprotectHint: &#039;Allow %s to be edited by anyone again&#039;,&lt;br /&gt;
		&#039;send thanks&#039;: &#039;send thanks&#039;,&lt;br /&gt;
		ThanksHint: &#039;Send a thank you notification to this user&#039;,&lt;br /&gt;
		move: &#039;move&#039;,&lt;br /&gt;
		&#039;move page&#039;: &#039;move page&#039;,&lt;br /&gt;
		MovepageHint: &#039;Change the title of %s&#039;,&lt;br /&gt;
		edit: &#039;edit&#039;, ///// edit articles and talk&lt;br /&gt;
		&#039;edit article&#039;: &#039;edit article&#039;,&lt;br /&gt;
		editHint: &#039;Change the content of %s&#039;,&lt;br /&gt;
		&#039;edit talk&#039;: &#039;edit talk&#039;,&lt;br /&gt;
		new: &#039;new&#039;,&lt;br /&gt;
		&#039;new topic&#039;: &#039;new topic&#039;,&lt;br /&gt;
		newSectionHint: &#039;Start a new section on %s&#039;,&lt;br /&gt;
		&#039;null edit&#039;: &#039;null edit&#039;,&lt;br /&gt;
		nullEditHint: &#039;Submit an edit to %s, making no changes &#039;,&lt;br /&gt;
		hist: &#039;hist&#039;, ///// history, diffs, editors, related&lt;br /&gt;
		history: &#039;history&#039;,&lt;br /&gt;
		historyHint: &#039;List the changes made to %s&#039;,&lt;br /&gt;
		&#039;History preview failed&#039;: &#039;History preview failed :-(&#039;,&lt;br /&gt;
		last: &#039;prev&#039;, // For labelling the previous revision in history pages; the key is &amp;quot;last&amp;quot; for backwards compatibility&lt;br /&gt;
		lastEdit: &#039;lastEdit&#039;,&lt;br /&gt;
		&#039;mark patrolled&#039;: &#039;mark patrolled&#039;,&lt;br /&gt;
		markpatrolledHint: &#039;Mark this edit as patrolled&#039;,&lt;br /&gt;
		&#039;Could not marked this edit as patrolled&#039;: &#039;Could not marked this edit as patrolled&#039;,&lt;br /&gt;
		&#039;show last edit&#039;: &#039;most recent edit&#039;,&lt;br /&gt;
		&#039;Show the last edit&#039;: &#039;Show the effects of the most recent change&#039;,&lt;br /&gt;
		lastContrib: &#039;lastContrib&#039;,&lt;br /&gt;
		&#039;last set of edits&#039;: &#039;latest edits&#039;,&lt;br /&gt;
		lastContribHint: &#039;Show the net effect of changes made by the last editor&#039;,&lt;br /&gt;
		cur: &#039;cur&#039;,&lt;br /&gt;
		diffCur: &#039;diffCur&#039;,&lt;br /&gt;
		&#039;Show changes since revision %s&#039;: &#039;Show changes since revision %s&#039;,&lt;br /&gt;
		&#039;%s old&#039;: &#039;%s old&#039;, // as in 4 weeks old&lt;br /&gt;
		oldEdit: &#039;oldEdit&#039;,&lt;br /&gt;
		purge: &#039;purge&#039;,&lt;br /&gt;
		purgeHint: &#039;Demand a fresh copy of %s&#039;,&lt;br /&gt;
		raw: &#039;source&#039;,&lt;br /&gt;
		rawHint: &#039;Download the source of %s&#039;,&lt;br /&gt;
		render: &#039;simple&#039;,&lt;br /&gt;
		renderHint: &#039;Show a plain HTML version of %s&#039;,&lt;br /&gt;
		&#039;Show the edit made to get revision&#039;: &#039;Show the edit made to get revision&#039;,&lt;br /&gt;
		sinceMe: &#039;sinceMe&#039;,&lt;br /&gt;
		&#039;changes since mine&#039;: &#039;diff my edit&#039;,&lt;br /&gt;
		sinceMeHint: &#039;Show changes since my last edit&#039;,&lt;br /&gt;
		&amp;quot;Couldn&#039;t find an edit by %s\nin the last %s edits to\n%s&amp;quot;:&lt;br /&gt;
			&amp;quot;Couldn&#039;t find an edit by %s\nin the last %s edits to\n%s&amp;quot;,&lt;br /&gt;
		eds: &#039;eds&#039;,&lt;br /&gt;
		editors: &#039;editors&#039;,&lt;br /&gt;
		editorListHint: &#039;List the users who have edited %s&#039;,&lt;br /&gt;
		related: &#039;related&#039;,&lt;br /&gt;
		relatedChanges: &#039;relatedChanges&#039;,&lt;br /&gt;
		&#039;related changes&#039;: &#039;related changes&#039;,&lt;br /&gt;
		RecentchangeslinkedHint: &#039;Show changes in articles related to %s&#039;,&lt;br /&gt;
		editOld: &#039;editOld&#039;, ///// edit old version, or revert&lt;br /&gt;
		rv: &#039;rv&#039;,&lt;br /&gt;
		revert: &#039;revert&#039;,&lt;br /&gt;
		revertHint: &#039;Revert to %s&#039;,&lt;br /&gt;
		defaultpopupReviewedSummary:&lt;br /&gt;
			&#039;Accepted by reviewing the [[Special:diff/%s/%s|difference]] between this version and previously accepted version using [[:en:Wikipedia:Tools/Navigation_popups|popups]]&#039;,&lt;br /&gt;
		defaultpopupRedlinkSummary:&lt;br /&gt;
			&#039;Removing link to empty page [[%s]] using [[:en:Wikipedia:Tools/Navigation_popups|popups]]&#039;,&lt;br /&gt;
		defaultpopupFixDabsSummary:&lt;br /&gt;
			&#039;Disambiguate [[%s]] to [[%s]] using [[:en:Wikipedia:Tools/Navigation_popups|popups]]&#039;,&lt;br /&gt;
		defaultpopupFixRedirsSummary:&lt;br /&gt;
			&#039;Redirect bypass from [[%s]] to [[%s]] using [[:en:Wikipedia:Tools/Navigation_popups|popups]]&#039;,&lt;br /&gt;
		defaultpopupExtendedRevertSummary:&lt;br /&gt;
			&#039;Revert to revision dated %s by %s, oldid %s using [[:en:Wikipedia:Tools/Navigation_popups|popups]]&#039;,&lt;br /&gt;
		defaultpopupRevertToPreviousSummary:&lt;br /&gt;
			&#039;Revert to the revision prior to revision %s using [[:en:Wikipedia:Tools/Navigation_popups|popups]]&#039;,&lt;br /&gt;
		defaultpopupRevertSummary:&lt;br /&gt;
			&#039;Revert to revision %s using [[:en:Wikipedia:Tools/Navigation_popups|popups]]&#039;,&lt;br /&gt;
		defaultpopupQueriedRevertToPreviousSummary:&lt;br /&gt;
			&#039;Revert to the revision prior to revision $1 dated $2 by $3 using [[:en:Wikipedia:Tools/Navigation_popups|popups]]&#039;,&lt;br /&gt;
		defaultpopupQueriedRevertSummary:&lt;br /&gt;
			&#039;Revert to revision $1 dated $2 by $3 using [[:en:Wikipedia:Tools/Navigation_popups|popups]]&#039;,&lt;br /&gt;
		defaultpopupRmDabLinkSummary:&lt;br /&gt;
			&#039;Remove link to dab page [[%s]] using [[:en:Wikipedia:Tools/Navigation_popups|popups]]&#039;,&lt;br /&gt;
		Redirects: &#039;Redirects&#039;, // as in Redirects to ...&lt;br /&gt;
		&#039; to &#039;: &#039; to &#039;, // as in Redirects to ...&lt;br /&gt;
		&#039;Bypass redirect&#039;: &#039;Bypass redirect&#039;,&lt;br /&gt;
		&#039;Fix this redirect&#039;: &#039;Fix this redirect&#039;,&lt;br /&gt;
		disambig: &#039;disambig&#039;, ///// add or remove dab etc.&lt;br /&gt;
		disambigHint: &#039;Disambiguate this link to [[%s]]&#039;,&lt;br /&gt;
		&#039;Click to disambiguate this link to:&#039;: &#039;Click to disambiguate this link to:&#039;,&lt;br /&gt;
		&#039;remove this link&#039;: &#039;remove this link&#039;,&lt;br /&gt;
		&#039;remove all links to this page from this article&#039;:&lt;br /&gt;
			&#039;remove all links to this page from this article&#039;,&lt;br /&gt;
		&#039;remove all links to this disambig page from this article&#039;:&lt;br /&gt;
			&#039;remove all links to this disambig page from this article&#039;,&lt;br /&gt;
		mainlink: &#039;mainlink&#039;, ///// links, watch, unwatch&lt;br /&gt;
		wikiLink: &#039;wikiLink&#039;,&lt;br /&gt;
		wikiLinks: &#039;wikiLinks&#039;,&lt;br /&gt;
		&#039;links here&#039;: &#039;links here&#039;,&lt;br /&gt;
		whatLinksHere: &#039;whatLinksHere&#039;,&lt;br /&gt;
		&#039;what links here&#039;: &#039;what links here&#039;,&lt;br /&gt;
		WhatlinkshereHint: &#039;List the pages that are hyperlinked to %s&#039;,&lt;br /&gt;
		unwatchShort: &#039;un&#039;,&lt;br /&gt;
		watchThingy: &#039;watch&#039;, // called watchThingy because {}.watch is a function&lt;br /&gt;
		watchHint: &#039;Add %s to my watchlist&#039;,&lt;br /&gt;
		unwatchHint: &#039;Remove %s from my watchlist&#039;,&lt;br /&gt;
		&#039;Only found one editor: %s made %s edits&#039;: &#039;Only found one editor: %s made %s edits&#039;,&lt;br /&gt;
		&#039;%s seems to be the last editor to the page %s&#039;:&lt;br /&gt;
			&#039;%s seems to be the last editor to the page %s&#039;,&lt;br /&gt;
		rss: &#039;rss&#039;,&lt;br /&gt;
		/////////////////////////////////////&lt;br /&gt;
		// diff previews&lt;br /&gt;
		/////////////////////////////////////&lt;br /&gt;
		&#039;Diff truncated for performance reasons&#039;: &#039;Diff truncated for performance reasons&#039;,&lt;br /&gt;
		&#039;Old revision&#039;: &#039;Old revision&#039;,&lt;br /&gt;
		&#039;New revision&#039;: &#039;New revision&#039;,&lt;br /&gt;
		&#039;Something went wrong :-(&#039;: &#039;Something went wrong :-(&#039;,&lt;br /&gt;
		&#039;Empty revision, maybe non-existent&#039;: &#039;Empty revision, maybe non-existent&#039;,&lt;br /&gt;
		&#039;Unknown date&#039;: &#039;Unknown date&#039;,&lt;br /&gt;
		/////////////////////////////////////&lt;br /&gt;
		// other special previews&lt;br /&gt;
		/////////////////////////////////////&lt;br /&gt;
		&#039;Empty category&#039;: &#039;Empty category&#039;,&lt;br /&gt;
		&#039;Category members (%s shown)&#039;: &#039;Category members (%s shown)&#039;,&lt;br /&gt;
		&#039;No image links found&#039;: &#039;No image links found&#039;,&lt;br /&gt;
		&#039;File links&#039;: &#039;File links&#039;,&lt;br /&gt;
		&#039;No image found&#039;: &#039;No image found&#039;,&lt;br /&gt;
		&#039;Image from Commons&#039;: &#039;Image from Commons&#039;,&lt;br /&gt;
		&#039;Description page&#039;: &#039;Description page&#039;,&lt;br /&gt;
		&#039;Alt text:&#039;: &#039;Alt text:&#039;,&lt;br /&gt;
		revdel: &#039;Hidden revision&#039;,&lt;br /&gt;
		/////////////////////////////////////&lt;br /&gt;
		// user-related actions and info&lt;br /&gt;
		/////////////////////////////////////&lt;br /&gt;
		user: &#039;user&#039;, ///// user page, talk, email, space&lt;br /&gt;
		&#039;user&amp;amp;nbsp;page&#039;: &#039;user&amp;amp;nbsp;page&#039;,&lt;br /&gt;
		&#039;user talk&#039;: &#039;user talk&#039;,&lt;br /&gt;
		&#039;edit user talk&#039;: &#039;edit user talk&#039;,&lt;br /&gt;
		&#039;leave comment&#039;: &#039;leave comment&#039;,&lt;br /&gt;
		email: &#039;email&#039;,&lt;br /&gt;
		&#039;email user&#039;: &#039;email user&#039;,&lt;br /&gt;
		EmailuserHint: &#039;Send an email to %s&#039;,&lt;br /&gt;
		space: &#039;space&#039;, // short form for userSpace link&lt;br /&gt;
		PrefixIndexHint: &#039;Show pages in the userspace of %s&#039;,&lt;br /&gt;
		count: &#039;count&#039;, ///// contributions, log&lt;br /&gt;
		&#039;edit counter&#039;: &#039;edit counter&#039;,&lt;br /&gt;
		editCounterLinkHint: &#039;Count the contributions made by %s&#039;,&lt;br /&gt;
		contribs: &#039;contribs&#039;,&lt;br /&gt;
		contributions: &#039;contributions&#039;,&lt;br /&gt;
		deletedContribs: &#039;deleted contributions&#039;,&lt;br /&gt;
		DeletedcontributionsHint: &#039;List deleted edits made by %s&#039;,&lt;br /&gt;
		ContributionsHint: &#039;List the contributions made by %s&#039;,&lt;br /&gt;
		log: &#039;log&#039;,&lt;br /&gt;
		&#039;user log&#039;: &#039;user log&#039;,&lt;br /&gt;
		userLogHint: &amp;quot;Show %s&#039;s user log&amp;quot;,&lt;br /&gt;
		arin: &#039;ARIN lookup&#039;, ///// ARIN lookup, block user or IP&lt;br /&gt;
		&#039;Look up %s in ARIN whois database&#039;: &#039;Look up %s in the ARIN whois database&#039;,&lt;br /&gt;
		unblockShort: &#039;un&#039;,&lt;br /&gt;
		block: &#039;block&#039;,&lt;br /&gt;
		&#039;block user&#039;: &#039;block user&#039;,&lt;br /&gt;
		IpblocklistHint: &#039;Unblock %s&#039;,&lt;br /&gt;
		BlockipHint: &#039;Prevent %s from editing&#039;,&lt;br /&gt;
		&#039;block log&#039;: &#039;block log&#039;,&lt;br /&gt;
		blockLogHint: &#039;Show the block log for %s&#039;,&lt;br /&gt;
		protectLogHint: &#039;Show the protection log for %s&#039;,&lt;br /&gt;
		pageLogHint: &#039;Show the page log for %s&#039;,&lt;br /&gt;
		deleteLogHint: &#039;Show the deletion log for %s&#039;,&lt;br /&gt;
		&#039;Invalid %s %s&#039;: &#039;The option %s is invalid: %s&#039;,&lt;br /&gt;
		&#039;No backlinks found&#039;: &#039;No backlinks found&#039;,&lt;br /&gt;
		&#039; and more&#039;: &#039; and more&#039;,&lt;br /&gt;
		undo: &#039;undo&#039;,&lt;br /&gt;
		undoHint: &#039;undo this edit&#039;,&lt;br /&gt;
		&#039;Download preview data&#039;: &#039;Download preview data&#039;,&lt;br /&gt;
		&#039;Invalid or IP user&#039;: &#039;Invalid or IP user&#039;,&lt;br /&gt;
		&#039;Not a registered username&#039;: &#039;Not a registered username&#039;,&lt;br /&gt;
		BLOCKED: &#039;BLOCKED&#039;,&lt;br /&gt;
		&#039;Has blocks&#039;: &#039;Has blocks&#039;,&lt;br /&gt;
		&#039; edits since: &#039;: &#039; edits since: &#039;,&lt;br /&gt;
		&#039;last edit on &#039;: &#039;last edit on &#039;,&lt;br /&gt;
		&#039;he/him&#039;: &#039;he/him&#039;,&lt;br /&gt;
		&#039;she/her&#039;: &#039;she/her&#039;,&lt;br /&gt;
		/////////////////////////////////////&lt;br /&gt;
		// Autoediting&lt;br /&gt;
		/////////////////////////////////////&lt;br /&gt;
		&#039;Enter a non-empty edit summary or press cancel to abort&#039;:&lt;br /&gt;
			&#039;Enter a non-empty edit summary or press cancel to abort&#039;,&lt;br /&gt;
		&#039;Failed to get revision information, please edit manually.\n\n&#039;:&lt;br /&gt;
			&#039;Failed to get revision information, please edit manually.\n\n&#039;,&lt;br /&gt;
		&#039;The %s button has been automatically clicked. Please wait for the next page to load.&#039;:&lt;br /&gt;
			&#039;The %s button has been automatically clicked. Please wait for the next page to load.&#039;,&lt;br /&gt;
		&#039;Could not find button %s. Please check the settings in your javascript file.&#039;:&lt;br /&gt;
			&#039;Could not find button %s. Please check the settings in your javascript file.&#039;,&lt;br /&gt;
		/////////////////////////////////////&lt;br /&gt;
		// Popups setup&lt;br /&gt;
		/////////////////////////////////////&lt;br /&gt;
		&#039;Open full-size image&#039;: &#039;Open full-size image&#039;,&lt;br /&gt;
		zxy: &#039;zxy&#039;,&lt;br /&gt;
		autoedit_version: &#039;np20140416&#039;,&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function popupString(str) {&lt;br /&gt;
		if (typeof popupStrings != &#039;undefined&#039; &amp;amp;&amp;amp; popupStrings &amp;amp;&amp;amp; popupStrings[str]) {&lt;br /&gt;
			return popupStrings[str];&lt;br /&gt;
		}&lt;br /&gt;
		if (pg.string[str]) {&lt;br /&gt;
			return pg.string[str];&lt;br /&gt;
		}&lt;br /&gt;
		return str;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function tprintf(str, subs) {&lt;br /&gt;
		if (typeof subs != typeof []) {&lt;br /&gt;
			subs = [subs];&lt;br /&gt;
		}&lt;br /&gt;
		return simplePrintf(popupString(str), subs);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ENDFILE: strings.js&lt;br /&gt;
&lt;br /&gt;
	// STARTFILE: run.js&lt;br /&gt;
	////////////////////////////////////////////////////////////////////&lt;br /&gt;
	// Run things&lt;br /&gt;
	////////////////////////////////////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
	// For some reason popups requires a fully loaded page jQuery.ready(...) causes problems for some.&lt;br /&gt;
	// The old addOnloadHook did something similar to the below&lt;br /&gt;
	if (document.readyState == &#039;complete&#039;) {&lt;br /&gt;
		autoEdit();&lt;br /&gt;
	}&lt;br /&gt;
	//will setup popups&lt;br /&gt;
	else {&lt;br /&gt;
		$(window).on(&#039;load&#039;, autoEdit);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Support for MediaWiki&#039;s live preview, VisualEditor&#039;s saves and Echo&#039;s flyout.&lt;br /&gt;
	(function () {&lt;br /&gt;
		let once = true;&lt;br /&gt;
		function dynamicContentHandler($content) {&lt;br /&gt;
			// Try to detect the hook fired on initial page load and disregard&lt;br /&gt;
			// it, we already hook to onload (possibly to different parts of&lt;br /&gt;
			// page - it&#039;s configurable) and running twice might be bad. Ugly…&lt;br /&gt;
			if ($content.attr(&#039;id&#039;) == &#039;mw-content-text&#039;) {&lt;br /&gt;
				if (once) {&lt;br /&gt;
					once = false;&lt;br /&gt;
					return;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			function registerHooksForVisibleNavpops() {&lt;br /&gt;
				for (let i = 0; pg.current.links &amp;amp;&amp;amp; i &amp;lt; pg.current.links.length; ++i) {&lt;br /&gt;
					const navpop = pg.current.links[i].navpopup;&lt;br /&gt;
					if (!navpop || !navpop.isVisible()) {&lt;br /&gt;
						continue;&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					Navpopup.tracker.addHook(posCheckerHook(navpop));&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			function doIt() {&lt;br /&gt;
				registerHooksForVisibleNavpops();&lt;br /&gt;
				$content.each(function () {&lt;br /&gt;
					this.ranSetupTooltipsAlready = false;&lt;br /&gt;
					setupTooltips(this);&lt;br /&gt;
				});&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			setupPopups(doIt);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// This hook is also fired after page load.&lt;br /&gt;
		mw.hook(&#039;wikipage.content&#039;).add(dynamicContentHandler);&lt;br /&gt;
&lt;br /&gt;
		mw.hook(&#039;ext.echo.overlay.beforeShowingOverlay&#039;).add(($overlay) =&amp;gt; {&lt;br /&gt;
			dynamicContentHandler($overlay.find(&#039;.mw-echo-state&#039;));&lt;br /&gt;
		});&lt;br /&gt;
	}());&lt;br /&gt;
});&lt;br /&gt;
// ENDFILE: run.js&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-Navigation_popups&amp;diff=120537</id>
		<title>MediaWiki:Gadget-Navigation popups</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-Navigation_popups&amp;diff=120537"/>
		<updated>2026-06-25T10:27:38Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Wikipedia:Tools/Navigation popups|Navigation popups]]: article previews and editing functions pop up when hovering over links&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=Template:ImageNoteEnd&amp;diff=120535</id>
		<title>Template:ImageNoteEnd</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=Template:ImageNoteEnd&amp;diff=120535"/>
		<updated>2026-06-25T10:27:28Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation|content=See [[Template:ImageWithNotes]].}}&lt;br /&gt;
[[Category:File namespace templates]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=Template:ImageNote&amp;diff=120533</id>
		<title>Template:ImageNote</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=Template:ImageNote&amp;diff=120533"/>
		<updated>2026-06-25T10:27:28Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#if: {{{style|}}} |&amp;lt;div id=&amp;quot;image_annotation_note_{{{id|{{{1}}}}}}&amp;quot; class=&amp;quot;image_annotation&amp;quot; style=&amp;quot;display:none;&amp;quot;&amp;gt;}}&lt;br /&gt;
&amp;lt;div class=&amp;quot;image_annotation_view_x_{{{id|{{{1}}}}}}&amp;quot; id=&amp;quot;image_annotation_view_x_{{{id|{{{1}}}}}}&amp;quot;&amp;gt;{{{x|{{{2}}}}}}&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;image_annotation_view_y_{{{id|{{{1}}}}}}&amp;quot; id=&amp;quot;image_annotation_view_y_{{{id|{{{1}}}}}}&amp;quot;&amp;gt;{{{y|{{{3}}}}}}&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;image_annotation_view_w_{{{id|{{{1}}}}}}&amp;quot; id=&amp;quot;image_annotation_view_w_{{{id|{{{1}}}}}}&amp;quot;&amp;gt;{{{w|{{{4}}}}}}&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;image_annotation_view_h_{{{id|{{{1}}}}}}&amp;quot; id=&amp;quot;image_annotation_view_h_{{{id|{{{1}}}}}}&amp;quot;&amp;gt;{{{h|{{{5}}}}}}&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;image_annotation_full_width_{{{id|{{{1}}}}}}&amp;quot; id=&amp;quot;image_annotation_full_width_{{{id|{{{1}}}}}}&amp;quot;&amp;gt;{{{dimx|{{{6}}}}}}&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;image_annotation_full_height_{{{id|{{{1}}}}}}&amp;quot; id=&amp;quot;image_annotation_full_height_{{{id|{{{1}}}}}}&amp;quot;&amp;gt;{{{dimy|{{{7}}}}}}&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;includeonly&amp;gt;{{#switch:{{NAMESPACE}}|File=[[Category:Images with annotations|{{PAGENAME}}]]}}&amp;lt;/includeonly&amp;gt;&lt;br /&gt;
{{#if: {{{style|}}} |&amp;lt;div class=&amp;quot;image_annotation_content_{{{id|{{{1}}}}}}&amp;quot; id=&amp;quot;image_annotation_content_{{{id|{{{1}}}}}}&amp;quot;&amp;gt;}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:File namespace templates]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-ImageAnnotator.js&amp;diff=120531</id>
		<title>MediaWiki:Gadget-ImageAnnotator.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-ImageAnnotator.js&amp;diff=120531"/>
		<updated>2026-06-25T10:27:28Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/*&lt;br /&gt;
  ImageAnnotator v2.3.2&lt;br /&gt;
&lt;br /&gt;
  Image annotations. Draw rectangles onto image thumbnail displayed on image description&lt;br /&gt;
  page and associate them with textual descriptions that will be displayed when the mouse&lt;br /&gt;
  moves over the rectangles. If an image has annotations, display the rectangles. Add a&lt;br /&gt;
  button to create new annotations.&lt;br /&gt;
&lt;br /&gt;
  Note: if an image that has annotations is overwritten by a new version, only display the&lt;br /&gt;
  annotations if the size of the top image matches the stored size exactly. To recover&lt;br /&gt;
  annotations, one will need to edit the image description page manually, adjusting image&lt;br /&gt;
  sizes and rectangle coordinates, or re-enter annotations.&lt;br /&gt;
&lt;br /&gt;
  Author: [[User:Lupo]], June 2009 - March 2010&lt;br /&gt;
  License: Quadruple licensed GFDL, GPL, LGPL and Creative Commons Attribution 3.0 (CC-BY-3.0)&lt;br /&gt;
&lt;br /&gt;
  Choose whichever license of these you like best :-)&lt;br /&gt;
&lt;br /&gt;
  See http://commons.wikimedia.org/wiki/Help:Gadget-ImageAnnotator for documentation.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/* global importScript, importScriptURI,&lt;br /&gt;
	LAPI, Tooltip, Tooltips, TextCleaner, UIElements, Buttons,&lt;br /&gt;
	ImageAnnotator, ImageAnnotator_disable */&lt;br /&gt;
/* eslint-disable one-var, vars-on-top, camelcase, no-use-before-define,&lt;br /&gt;
	eqeqeq, no-alert, no-loop-func, no-inner-declarations */&lt;br /&gt;
&lt;br /&gt;
if ( typeof ImageAnnotator === &#039;undefined&#039; ) { // Guard against multiple inclusions&lt;br /&gt;
&lt;br /&gt;
	importScript( &#039;MediaWiki:LAPI.js&#039; );&lt;br /&gt;
	importScript( &#039;MediaWiki:Tooltips.js&#039; );&lt;br /&gt;
	importScript( &#039;MediaWiki:TextCleaner.js&#039; );&lt;br /&gt;
	importScript( &#039;MediaWiki:UIElements.js&#039; );&lt;br /&gt;
&lt;br /&gt;
	( function () { // Local scope&lt;br /&gt;
&lt;br /&gt;
		var ImageAnnotator_config = null;&lt;br /&gt;
&lt;br /&gt;
		var ImageAnnotation = function () {&lt;br /&gt;
			this.initialize.apply( this, arguments );&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		ImageAnnotation.compare = function ( a, b ) {&lt;br /&gt;
			var result = b.area() - a.area();&lt;br /&gt;
			if ( result !== 0 ) { return result; }&lt;br /&gt;
			// Just to make sure the order is complete&lt;br /&gt;
			return a.model.id - b.model.id;&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		ImageAnnotation.prototype = {&lt;br /&gt;
			// Rectangle to be displayed on image: a div with pos and size&lt;br /&gt;
			view: null,&lt;br /&gt;
			// Internal representation of the annotation&lt;br /&gt;
			model: null,&lt;br /&gt;
			// Tooltip to display the annotation&lt;br /&gt;
			tooltip: null,&lt;br /&gt;
			// Content of the tooltip&lt;br /&gt;
			content: null,&lt;br /&gt;
			// Reference to the viewer this note belongs to&lt;br /&gt;
			viewer: null,&lt;br /&gt;
&lt;br /&gt;
			initialize: function ( node, viewer, id ) {&lt;br /&gt;
				var is_new = false;&lt;br /&gt;
				var view_w = 0, view_h = 0, view_x = 0, view_y = 0;&lt;br /&gt;
				this.viewer = viewer;&lt;br /&gt;
				if ( LAPI.DOM.hasClass( node, IA.annotation_class ) ) {&lt;br /&gt;
					// Extract the info we need&lt;br /&gt;
					var x = IA.getIntItem( &#039;view_x_&#039; + id, viewer.scope );&lt;br /&gt;
					var y = IA.getIntItem( &#039;view_y_&#039; + id, viewer.scope );&lt;br /&gt;
					var w = IA.getIntItem( &#039;view_w_&#039; + id, viewer.scope );&lt;br /&gt;
					var h = IA.getIntItem( &#039;view_h_&#039; + id, viewer.scope );&lt;br /&gt;
					var html = IA.getRawItem( &#039;content_&#039; + id, viewer.scope );&lt;br /&gt;
					if ( x === null || y === null || w === null || h === null || html === null ) { throw new Error( &#039;Invalid note&#039; ); }&lt;br /&gt;
					if ( x &amp;lt; 0 || x &amp;gt;= viewer.full_img.width || y &amp;lt; 0 || y &amp;gt;= viewer.full_img.height ) { throw new Error( &#039;Invalid note: origin invalid on note &#039; + id ); }&lt;br /&gt;
					if (&lt;br /&gt;
						x + w &amp;gt; viewer.full_img.width + 10 ||&lt;br /&gt;
						y + h &amp;gt; viewer.full_img.height + 10&lt;br /&gt;
					) {&lt;br /&gt;
						throw new Error( &#039;Invalid note: size extends beyond image on note &#039; + id );&lt;br /&gt;
					}&lt;br /&gt;
					// Notes written by early versions may be slightly too large, whence the + 10 above. Fix this.&lt;br /&gt;
					if ( x + w &amp;gt; viewer.full_img.width ) { w = viewer.full_img.width - x; }&lt;br /&gt;
					if ( y + h &amp;gt; viewer.full_img.height ) { h = viewer.full_img.height - y; }&lt;br /&gt;
					view_w = Math.floor( w / viewer.factors.dx );&lt;br /&gt;
					view_h = Math.floor( h / viewer.factors.dy );&lt;br /&gt;
					view_x = Math.floor( x / viewer.factors.dx );&lt;br /&gt;
					view_y = Math.floor( y / viewer.factors.dy );&lt;br /&gt;
					this.view = LAPI.make(&lt;br /&gt;
						&#039;div&#039;, null,&lt;br /&gt;
						{&lt;br /&gt;
							position: &#039;absolute&#039;,&lt;br /&gt;
							display: &#039;none&#039;,&lt;br /&gt;
							lineHeight: &#039;0px&#039;, // IE&lt;br /&gt;
							fontSize: &#039;0px&#039;, // IE&lt;br /&gt;
							top: String( view_y ) + &#039;px&#039;,&lt;br /&gt;
							left: String( view_x ) + &#039;px&#039;,&lt;br /&gt;
							width: String( view_w ) + &#039;px&#039;,&lt;br /&gt;
							height: String( view_h ) + &#039;px&#039;&lt;br /&gt;
						}&lt;br /&gt;
					);&lt;br /&gt;
					// We&#039;ll add the view to the DOM once we&#039;ve loaded all notes&lt;br /&gt;
					this.model = {&lt;br /&gt;
						id: id,&lt;br /&gt;
						dimension: { x: x, y: y, w: w, h: h },&lt;br /&gt;
						wiki: &#039;&#039;,&lt;br /&gt;
						html: html.cloneNode( true )&lt;br /&gt;
					};&lt;br /&gt;
				} else {&lt;br /&gt;
					is_new = true;&lt;br /&gt;
					this.view = node;&lt;br /&gt;
					this.model = {&lt;br /&gt;
						id: -1,&lt;br /&gt;
						dimension: null,&lt;br /&gt;
						wiki: &#039;&#039;,&lt;br /&gt;
						html: null&lt;br /&gt;
					};&lt;br /&gt;
					view_w = this.view.offsetWidth - 2; // Subtract cumulated border widths&lt;br /&gt;
					view_h = this.view.offsetHeight - 2;&lt;br /&gt;
					view_x = this.view.offsetLeft;&lt;br /&gt;
					view_y = this.view.offsetTop;&lt;br /&gt;
				}&lt;br /&gt;
				// Enforce a minimum size of the view. Center the 6x6px square over the center of the old view.&lt;br /&gt;
				// If we overlap the image boundary, adjustRectangleSize will take care of it later.&lt;br /&gt;
				if ( view_w &amp;lt; 6 ) { view_x = Math.floor( view_x + view_w / 2 - 3 ); view_w = 6; }&lt;br /&gt;
				if ( view_h &amp;lt; 6 ) { view_y = Math.floor( view_y + view_h / 2 - 3 ); view_h = 6; }&lt;br /&gt;
				Object.merge(&lt;br /&gt;
					{&lt;br /&gt;
						left: String( view_x ) + &#039;px&#039;,&lt;br /&gt;
						top: String( view_y ) + &#039;px&#039;,&lt;br /&gt;
						width: String( view_w ) + &#039;px&#039;,&lt;br /&gt;
						height: String( view_h ) + &#039;px&#039;&lt;br /&gt;
					},&lt;br /&gt;
					this.view.style&lt;br /&gt;
				);&lt;br /&gt;
				this.view.style.zIndex = 500; // Below tooltips&lt;br /&gt;
				try {&lt;br /&gt;
					this.view.style.border = &#039;1px solid &#039; + this.viewer.outer_border;&lt;br /&gt;
				} catch ( ex ) {&lt;br /&gt;
					this.view.style.border = &#039;1px solid &#039; + IA.outer_border;&lt;br /&gt;
				}&lt;br /&gt;
				this.view.appendChild(&lt;br /&gt;
					LAPI.make(&lt;br /&gt;
						&#039;div&#039;, null&lt;br /&gt;
						, { lineHeight: &#039;0px&#039;, // IE&lt;br /&gt;
							fontSize: &#039;0px&#039;, // IE&lt;br /&gt;
							width: String( Math.max( view_w - 2, 0 ) ) + &#039;px&#039;, // -2 to leave space for the border&lt;br /&gt;
							height: String( Math.max( view_h - 2, 0 ) ) + &#039;px&#039;&lt;br /&gt;
						}&lt;br /&gt;
					)&lt;br /&gt;
					// width=100% doesn&#039;t work right: inner div&#039;s border appears outside on right and bottom on FF.&lt;br /&gt;
				);&lt;br /&gt;
				try {&lt;br /&gt;
					this.view.firstChild.style.border = &#039;1px solid &#039; + this.viewer.inner_border;&lt;br /&gt;
				} catch ( ex ) {&lt;br /&gt;
					this.view.firstChild.style.border = &#039;1px solid &#039; + IA.inner_border;&lt;br /&gt;
				}&lt;br /&gt;
				if ( is_new ) { viewer.adjustRectangleSize( this.view ); }&lt;br /&gt;
				// IE somehow passes through event to the view even if covered by our cover, displaying the tooltips&lt;br /&gt;
				// when drawing a new rectangle, which is confusing and produces a selection nightmare. Hence we just&lt;br /&gt;
				// display raw rectangles without any tooltips attached while drawing. Yuck.&lt;br /&gt;
				this.dummy = this.view.cloneNode( true );&lt;br /&gt;
				viewer.img_div.appendChild( this.dummy );&lt;br /&gt;
				if ( !is_new ) {&lt;br /&gt;
					// New notes get their tooltip only once the editor has saved, otherwise IE may try to&lt;br /&gt;
					// open them if the mouse moves onto the view even though there is the cover above them!&lt;br /&gt;
					this.setTooltip();&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			setTooltip: function () {&lt;br /&gt;
				if ( this.tooltip || !this.view ) { return; } // Already set, or corrupt&lt;br /&gt;
				// Note: on IE, don&#039;t have tooltips appear automatically. IE doesn&#039;t do it right for transparent&lt;br /&gt;
				// targets and we have to show and hide them ourselves through a mousemove listener in the viewer&lt;br /&gt;
				// anyway. The occasional event that IE sends to the tooltip may then lead to ugly flickering.&lt;br /&gt;
				this.tooltip = new Tooltip(&lt;br /&gt;
					this.view.firstChild,&lt;br /&gt;
					this.display.bind( this ),&lt;br /&gt;
					{&lt;br /&gt;
						activate: ( LAPI.DOM.is_ie ? Tooltip.NONE : Tooltip.HOVER ),&lt;br /&gt;
						deactivate: ( LAPI.DOM.is_ie ? Tooltip.ESCAPE : Tooltip.LEAVE ),&lt;br /&gt;
						close_button: null,&lt;br /&gt;
						mode: Tooltip.MOUSE,&lt;br /&gt;
						mouse_offset: { x: -5, y: -5, dx: ( IA.is_rtl ? -1 : 1 ), dy: 1 },&lt;br /&gt;
						open_delay: 0,&lt;br /&gt;
						hide_delay: 0,&lt;br /&gt;
						onclose: ( function ( tooltip, evt ) {&lt;br /&gt;
							if ( this.view ) {&lt;br /&gt;
								try {&lt;br /&gt;
									this.view.style.border = &#039;1px solid &#039; + this.viewer.outer_border;&lt;br /&gt;
								} catch ( ex ) {&lt;br /&gt;
									this.view.style.border = &#039;1px solid &#039; + IA.outer_border;&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
							if ( this.viewer.tip == tooltip ) { this.viewer.tip = null; }&lt;br /&gt;
							// Hide all boxes if we&#039;re outside the image. Relies on hide checking the&lt;br /&gt;
							// coordinates! (Otherwise, we&#039;d always hide...)&lt;br /&gt;
							if ( evt ) { this.viewer.hide( evt ); }&lt;br /&gt;
						} ).bind( this ),&lt;br /&gt;
						onopen: ( function ( tooltip ) {&lt;br /&gt;
							if ( this.view ) {&lt;br /&gt;
								try {&lt;br /&gt;
									this.view.style.border = &#039;1px solid &#039; + this.viewer.active_border;&lt;br /&gt;
								} catch ( ex ) {&lt;br /&gt;
									this.view.style.border = &#039;1px solid &#039; + IA.active_border;&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
							this.viewer.tip = tooltip;&lt;br /&gt;
						} ).bind( this )&lt;br /&gt;
					},&lt;br /&gt;
					IA.tooltip_styles&lt;br /&gt;
				);&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			display: function ( evt ) {&lt;br /&gt;
				if ( !this.content ) {&lt;br /&gt;
					this.content = LAPI.make( &#039;div&#039; );&lt;br /&gt;
					var main = LAPI.make( &#039;div&#039; );&lt;br /&gt;
					this.content.appendChild( main );&lt;br /&gt;
					this.content.main = main;&lt;br /&gt;
					if ( this.model.html ) { main.appendChild( this.model.html.cloneNode( true ) ); }&lt;br /&gt;
					// Make sure that the popup encompasses all floats&lt;br /&gt;
					this.content.appendChild( LAPI.make( &#039;div&#039;, null, { clear: &#039;both&#039; } ) );&lt;br /&gt;
					if ( this.viewer.may_edit ) {&lt;br /&gt;
						this.content.button_section = LAPI.make(&lt;br /&gt;
							&#039;div&#039;,&lt;br /&gt;
							null,&lt;br /&gt;
							{&lt;br /&gt;
								fontSize: &#039;smaller&#039;,&lt;br /&gt;
								textAlign: ( IA.is_rtl ? &#039;left&#039; : &#039;right&#039; ),&lt;br /&gt;
								borderTop: IA.tooltip_styles.border&lt;br /&gt;
							}&lt;br /&gt;
						);&lt;br /&gt;
						this.content.appendChild( this.content.button_section );&lt;br /&gt;
						this.content.button_section.appendChild( LAPI.DOM.makeLink(&lt;br /&gt;
							&#039;#&#039;,&lt;br /&gt;
							ImageAnnotator.UI.get( &#039;wpImageAnnotatorEdit&#039;, true ),&lt;br /&gt;
							null,&lt;br /&gt;
							LAPI.Evt.makeListener( this, this.edit )&lt;br /&gt;
						) );&lt;br /&gt;
						if ( ImageAnnotator_config.mayDelete() ) {&lt;br /&gt;
							this.content.button_section.appendChild( document.createTextNode( &#039;\xa0&#039; ) );&lt;br /&gt;
							this.content.button_section.appendChild( LAPI.DOM.makeLink(&lt;br /&gt;
								&#039;#&#039;,&lt;br /&gt;
								ImageAnnotator.UI.get( &#039;wpImageAnnotatorDelete&#039;, true ),&lt;br /&gt;
								null,&lt;br /&gt;
								LAPI.Evt.makeListener( this, this.remove_event )&lt;br /&gt;
							) );&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				return this.content;&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			edit: function ( evt ) {&lt;br /&gt;
				if ( IA.canEdit() ) { IA.editor.editNote( this ); }&lt;br /&gt;
				if ( evt ) { return LAPI.Evt.kill( evt ); }&lt;br /&gt;
				return false;&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			remove_event: function ( evt ) {&lt;br /&gt;
				if ( IA.canEdit() ) { this.remove(); }&lt;br /&gt;
				return LAPI.Evt.kill( evt );&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			remove: function () {&lt;br /&gt;
				if ( !this.content ) { // New note: just destroy it.&lt;br /&gt;
					this.destroy();&lt;br /&gt;
					return true;&lt;br /&gt;
				}&lt;br /&gt;
				if ( !ImageAnnotator_config.mayDelete() ) { return false; }&lt;br /&gt;
&lt;br /&gt;
				// Close and remove tooltip only if edit succeeded! Where and how to display error messages?&lt;br /&gt;
&lt;br /&gt;
				var reason = &#039;&#039;;&lt;br /&gt;
				if ( !ImageAnnotator_config.mayBypassDeletionPrompt() || !window.ImageAnnotator_noDeletionPrompt ) {&lt;br /&gt;
					// Prompt for a removal reson&lt;br /&gt;
					reason = prompt( ImageAnnotator.UI.get( &#039;wpImageAnnotatorDeleteReason&#039;, true ), &#039;&#039; );&lt;br /&gt;
					if ( reason === null ) { return false; } // Cancelled&lt;br /&gt;
					reason = reason.trim();&lt;br /&gt;
					if ( !reason.length ) {&lt;br /&gt;
						if ( !ImageAnnotator_config.emptyDeletionReasonAllowed() ) { return false; }&lt;br /&gt;
					}&lt;br /&gt;
					// Re-show tooltip (without re-positioning it, we have no mouse coordinates here) in case&lt;br /&gt;
					// it was hidden because of the alert. If possible, we want the user to see the spinner.&lt;br /&gt;
					this.tooltip.show_now( this.tooltip );&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				var self = this;&lt;br /&gt;
				var spinnerId = &#039;image_annotation_delete_&#039; + this.model.id;&lt;br /&gt;
				LAPI.Ajax.injectSpinner( this.content.button_section.lastChild, spinnerId );&lt;br /&gt;
				if ( this.tooltip ) { this.tooltip.size_change(); }&lt;br /&gt;
				LAPI.Ajax.editPage(&lt;br /&gt;
					mw.config.get( &#039;wgPageName&#039; ),&lt;br /&gt;
					function ( doc, editForm, failureFunc, revision_id ) {&lt;br /&gt;
						try {&lt;br /&gt;
							if ( revision_id &amp;amp;&amp;amp; revision_id != mw.config.get( &#039;wgCurRevisionId&#039; ) ) { throw new Error( &#039;#Page version (revision ID) mismatch: edit conflict.&#039; ); }&lt;br /&gt;
&lt;br /&gt;
							var textbox = editForm.wpTextbox1;&lt;br /&gt;
							if ( !textbox ) { throw new Error( &#039;#Server replied with invalid edit page.&#039; ); }&lt;br /&gt;
							var pagetext = textbox.value.replace( /\r\n/g, &#039;\n&#039; );&lt;br /&gt;
							// Normalize different end-of-line handling. Opera and IE may use \r\n, whereas other&lt;br /&gt;
							// browsers just use &#039;\n&#039;. Note that all browsers do the right thing if a &#039;\n&#039; is added.&lt;br /&gt;
							// We normally don&#039;t care, but here we need this to make sure we don&#039;t leave extra line&lt;br /&gt;
							// breaks when we remove the note.&lt;br /&gt;
&lt;br /&gt;
							IA.setWikitext( pagetext );&lt;br /&gt;
&lt;br /&gt;
							var span = IA.findNote( pagetext, self.model.id );&lt;br /&gt;
							if ( !span ) { // Hmmm? Doesn&#039;t seem to exist&lt;br /&gt;
								LAPI.Ajax.removeSpinner( spinnerId );&lt;br /&gt;
								if ( self.tooltip ) { self.tooltip.size_change(); }&lt;br /&gt;
								self.destroy();&lt;br /&gt;
								return;&lt;br /&gt;
							}&lt;br /&gt;
							var char_before = 0;&lt;br /&gt;
							var char_after = 0;&lt;br /&gt;
							if ( span.start &amp;gt; 0 ) { char_before = pagetext.charCodeAt( span.start - 1 ); }&lt;br /&gt;
							if ( span.end &amp;lt; pagetext.length ) { char_after = pagetext.charCodeAt( span.end ); }&lt;br /&gt;
							if (&lt;br /&gt;
								String.fromCharCode( char_before ) == &#039;\n&#039; &amp;amp;&amp;amp;&lt;br /&gt;
								String.fromCharCode( char_after ) == &#039;\n&#039;&lt;br /&gt;
							) {&lt;br /&gt;
								span.start = span.start - 1;&lt;br /&gt;
							}&lt;br /&gt;
							pagetext = pagetext.substring( 0, span.start ) + pagetext.substring( span.end );&lt;br /&gt;
							textbox.value = pagetext;&lt;br /&gt;
							var summary = editForm.wpSummary;&lt;br /&gt;
							if ( !summary ) {&lt;br /&gt;
								throw new Error( &#039;#Summary field not found. Check that edit pages have valid XHTML.&#039; );&lt;br /&gt;
							}&lt;br /&gt;
							IA.setSummary(&lt;br /&gt;
								summary,&lt;br /&gt;
								ImageAnnotator.UI.get( &#039;wpImageAnnotatorRemoveSummary&#039;, true ) ||&lt;br /&gt;
									&#039;[[MediaWiki talk:Gadget-ImageAnnotator.js|Removing image note]]$1&#039;,&lt;br /&gt;
								( reason.length ? reason + &#039;: &#039; : &#039;&#039; ) + self.model.wiki&lt;br /&gt;
							);&lt;br /&gt;
						} catch ( ex ) {&lt;br /&gt;
							failure( null, ex );&lt;br /&gt;
							return;&lt;br /&gt;
						}&lt;br /&gt;
						var edit_page = doc;&lt;br /&gt;
						LAPI.Ajax.submitEdit(&lt;br /&gt;
							editForm,&lt;br /&gt;
							function ( request ) {&lt;br /&gt;
								if ( edit_page.isFake &amp;amp;&amp;amp; ( typeof edit_page.dispose === &#039;function&#039; ) ) { edit_page.dispose(); }&lt;br /&gt;
								var revision_id = LAPI.WP.revisionFromHtml( request.responseText );&lt;br /&gt;
								if ( !revision_id ) {&lt;br /&gt;
									failureFunc( request, new Error( &#039;Revision ID not found. Please reload the page.&#039; ) );&lt;br /&gt;
									return;&lt;br /&gt;
								}&lt;br /&gt;
								mw.config.set( &#039;wgCurRevisionId&#039;, revision_id ); // Bump revision id!!&lt;br /&gt;
								LAPI.Ajax.removeSpinner( spinnerId );&lt;br /&gt;
								if ( self.tooltip ) { self.tooltip.size_change(); }&lt;br /&gt;
								self.destroy();&lt;br /&gt;
							},&lt;br /&gt;
							function ( request, ex ) {&lt;br /&gt;
								if ( edit_page.isFake &amp;amp;&amp;amp; ( typeof edit_page.dispose === &#039;function&#039; ) ) { edit_page.dispose(); }&lt;br /&gt;
								failureFunc( request, ex );&lt;br /&gt;
							}&lt;br /&gt;
						);&lt;br /&gt;
					},&lt;br /&gt;
					function ( request, ex ) {&lt;br /&gt;
						// Failure. What now? TODO: Implement some kind of user feedback.&lt;br /&gt;
						LAPI.Ajax.removeSpinner( spinnerId );&lt;br /&gt;
						if ( self.tooltip ) { self.tooltip.size_change(); }&lt;br /&gt;
					}&lt;br /&gt;
				);&lt;br /&gt;
&lt;br /&gt;
				return true;&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			destroy: function () {&lt;br /&gt;
				if ( this.view ) { LAPI.DOM.removeNode( this.view ); }&lt;br /&gt;
				if ( this.dummy ) { LAPI.DOM.removeNode( this.dummy ); }&lt;br /&gt;
				if ( this.tooltip ) { this.tooltip.hide_now(); }&lt;br /&gt;
				if ( this.model &amp;amp;&amp;amp; this.model.id &amp;gt; 0 &amp;amp;&amp;amp; this.viewer ) { this.viewer.deregister( this ); }&lt;br /&gt;
				this.model = null;&lt;br /&gt;
				this.view = null;&lt;br /&gt;
				this.content = null;&lt;br /&gt;
				this.tooltip = null;&lt;br /&gt;
				this.viewer = null;&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			area: function () {&lt;br /&gt;
				if ( !this.model || !this.model.dimension ) { return 0; }&lt;br /&gt;
				return ( this.model.dimension.w * this.model.dimension.h );&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			cannotEdit: function () {&lt;br /&gt;
				if ( this.content &amp;amp;&amp;amp; this.content.button_section ) {&lt;br /&gt;
					LAPI.DOM.removeNode( this.content.button_section );&lt;br /&gt;
					this.content.button_section = null;&lt;br /&gt;
					if ( this.tooltip ) { this.tooltip.size_change(); }&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
		}; // end ImageAnnotation&lt;br /&gt;
&lt;br /&gt;
		var ImageAnnotationEditor = function () { this.initialize.apply( this, arguments ); };&lt;br /&gt;
&lt;br /&gt;
		ImageAnnotationEditor.prototype = {&lt;br /&gt;
			initialize: function () {&lt;br /&gt;
				var editor_width = 50;&lt;br /&gt;
				// Respect potential user-defined width setting&lt;br /&gt;
				if ( window.ImageAnnotationEditor_columns &amp;amp;&amp;amp;&lt;br /&gt;
				!isNaN( window.ImageAnnotationEditor_columns ) &amp;amp;&amp;amp;&lt;br /&gt;
				window.ImageAnnotationEditor_columns &amp;gt;= 30 &amp;amp;&amp;amp;&lt;br /&gt;
				window.ImageAnnotationEditor_columns &amp;lt;= 100 ) {&lt;br /&gt;
					editor_width = window.ImageAnnotationEditor_columns;&lt;br /&gt;
				}&lt;br /&gt;
				this.editor = new LAPI.Edit(&lt;br /&gt;
					&#039;&#039;, editor_width, 6,&lt;br /&gt;
					{&lt;br /&gt;
						box: ImageAnnotator.UI.get( &#039;wpImageAnnotatorEditorLabel&#039;, false ),&lt;br /&gt;
						preview: ImageAnnotator.UI.get( &#039;wpImageAnnotatorPreview&#039;, true ).capitalizeFirst(),&lt;br /&gt;
						save: ImageAnnotator.UI.get( &#039;wpImageAnnotatorSave&#039;, true ).capitalizeFirst(),&lt;br /&gt;
						revert: ImageAnnotator.UI.get( &#039;wpImageAnnotatorRevert&#039;, true ).capitalizeFirst(),&lt;br /&gt;
						cancel: ImageAnnotator.UI.get( &#039;wpImageAnnotatorCancel&#039;, true ).capitalizeFirst(),&lt;br /&gt;
						nullsave: ImageAnnotator_config.mayDelete() ?&lt;br /&gt;
							ImageAnnotator.UI.get( &#039;wpImageAnnotatorDelete&#039;, true ).capitalizeFirst() :&lt;br /&gt;
							null,&lt;br /&gt;
						post: ImageAnnotator.UI.get( &#039;wpImageAnnotatorCopyright&#039;, false )&lt;br /&gt;
					},&lt;br /&gt;
					{&lt;br /&gt;
						onsave: this.save.bind( this ),&lt;br /&gt;
						onpreview: this.onpreview.bind( this ),&lt;br /&gt;
						oncancel: this.cancel.bind( this ),&lt;br /&gt;
						ongettext: function ( text ) {&lt;br /&gt;
							if ( text == null ) { return &#039;&#039;; }&lt;br /&gt;
							text = text.trim()&lt;br /&gt;
								.replace( /\{\{(\s*ImageNote(End)?\s*\|)/g, &#039;&amp;amp;#x7B;&amp;amp;#x7B;$1&#039; );&lt;br /&gt;
							// Guard against people trying to break notes on purpose&lt;br /&gt;
							if ( text.length &amp;amp;&amp;amp; typeof TextCleaner !== &#039;undefined&#039; ) { text = TextCleaner.sanitizeWikiText( text, true ); }&lt;br /&gt;
							return text;&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				);&lt;br /&gt;
				this.box = LAPI.make( &#039;div&#039; );&lt;br /&gt;
				this.box.appendChild( this.editor.getView() );&lt;br /&gt;
				// Limit the width of the bounding box to the size of the textarea, taking into account the&lt;br /&gt;
				// tooltip styles. Do *not* simply append this.box or the editor view, Opera behaves strangely&lt;br /&gt;
				// if textboxes were ever hidden through a visibility setting! Use a second throw-away textbox&lt;br /&gt;
				// instead.&lt;br /&gt;
				var temp = LAPI.make( &#039;div&#039;, null, IA.tooltip_styles );&lt;br /&gt;
				temp.appendChild( LAPI.make( &#039;textarea&#039;, { cols: editor_width, rows: 6 } ) );&lt;br /&gt;
				Object.merge(&lt;br /&gt;
					{&lt;br /&gt;
						position: &#039;absolute&#039;,&lt;br /&gt;
						top: &#039;0px&#039;,&lt;br /&gt;
						left: &#039;-10000px&#039;,&lt;br /&gt;
						visibility: &#039;hidden&#039;&lt;br /&gt;
					},&lt;br /&gt;
					temp.style&lt;br /&gt;
				);&lt;br /&gt;
				document.body.appendChild( temp );&lt;br /&gt;
				// Now we know how wide this textbox will be&lt;br /&gt;
				var box_width = temp.offsetWidth;&lt;br /&gt;
				LAPI.DOM.removeNode( temp );&lt;br /&gt;
				// Note: we need to use a tooltip with a dynamic content creator function here because&lt;br /&gt;
				// static content is cloned inside the Tooltip. Cloning on IE loses all attached handlers,&lt;br /&gt;
				// and thus the editor&#039;s controls wouldn&#039;t work anymore. (This is not a problem on FF3,&lt;br /&gt;
				// where cloning preserves the handlers.)&lt;br /&gt;
				this.tooltip = new Tooltip(&lt;br /&gt;
					IA.get_cover(),&lt;br /&gt;
					this.get_editor.bind( this ),&lt;br /&gt;
					{&lt;br /&gt;
						activate: Tooltip.NONE, // We&#039;ll always show it explicitly&lt;br /&gt;
						deactivate: Tooltip.ESCAPE,&lt;br /&gt;
						close_button: null, // We have a cancel button anyway&lt;br /&gt;
						mode: Tooltip.FIXED,&lt;br /&gt;
						anchor: Tooltip.TOP_LEFT,&lt;br /&gt;
						mouse_offset: { x: 10, y: 10, dx: 1, dy: 1 }, // Misuse this: fixed offset from view&lt;br /&gt;
						max_pixels: ( box_width ? box_width + 20 : 0 ), // + 20 gives some slack&lt;br /&gt;
						z_index: 2010, // Above the cover.&lt;br /&gt;
						open_delay: 0,&lt;br /&gt;
						hide_delay: 0,&lt;br /&gt;
						onclose: this.close_tooltip.bind( this )&lt;br /&gt;
					},&lt;br /&gt;
					IA.tooltip_styles&lt;br /&gt;
				);&lt;br /&gt;
				this.note = null;&lt;br /&gt;
				this.visible = false;&lt;br /&gt;
				LAPI.Evt.listenTo( this, this.tooltip.popup, IA.mouse_in,&lt;br /&gt;
					function ( evt ) {&lt;br /&gt;
						Array.forEach( IA.viewers, ( function ( viewer ) {&lt;br /&gt;
							if ( viewer != this.viewer &amp;amp;&amp;amp; viewer.visible ) { viewer.hide(); }&lt;br /&gt;
						} ).bind( this ) );&lt;br /&gt;
					}&lt;br /&gt;
				);&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			get_editor: function () {&lt;br /&gt;
				return this.box;&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			editNote: function ( note ) {&lt;br /&gt;
				var same_note = ( note == this.note );&lt;br /&gt;
				this.note = note;&lt;br /&gt;
				this.viewer = this.note.viewer;&lt;br /&gt;
&lt;br /&gt;
				var cover = IA.get_cover();&lt;br /&gt;
				cover.style.cursor = &#039;auto&#039;;&lt;br /&gt;
				IA.show_cover();&lt;br /&gt;
&lt;br /&gt;
				if ( note.tooltip ) { note.tooltip.hide_now(); }&lt;br /&gt;
&lt;br /&gt;
				IA.is_editing = true;&lt;br /&gt;
				if ( note.content &amp;amp;&amp;amp; !IA.wiki_read ) {&lt;br /&gt;
					// Existing note, and we don&#039;t have the wikitext yet: go get it&lt;br /&gt;
					var self = this;&lt;br /&gt;
					LAPI.Ajax.apiGet(&lt;br /&gt;
						&#039;query&#039;,&lt;br /&gt;
						{&lt;br /&gt;
							prop: &#039;revisions&#039;,&lt;br /&gt;
							titles: mw.config.get( &#039;wgPageName&#039; ),&lt;br /&gt;
							rvlimit: 1,&lt;br /&gt;
							rvstartid: mw.config.get( &#039;wgCurRevisionId&#039; ),&lt;br /&gt;
							rvprop: &#039;ids|content&#039;&lt;br /&gt;
						},&lt;br /&gt;
						function ( request, json_result ) {&lt;br /&gt;
							if ( json_result &amp;amp;&amp;amp; json_result.query &amp;amp;&amp;amp; json_result.query.pages ) {&lt;br /&gt;
								// Should have only one page here&lt;br /&gt;
								for ( var page in json_result.query.pages ) {&lt;br /&gt;
									var p = json_result.query.pages[ page ];&lt;br /&gt;
									if ( p &amp;amp;&amp;amp; p.revisions &amp;amp;&amp;amp; p.revisions.length ) {&lt;br /&gt;
										var rev = p.revisions[ 0 ];&lt;br /&gt;
										if ( rev.revid == mw.config.get( &#039;wgCurRevisionId&#039; ) &amp;amp;&amp;amp; rev[ &#039;*&#039; ] &amp;amp;&amp;amp; rev[ &#039;*&#039; ].length ) { IA.setWikitext( rev[ &#039;*&#039; ] ); }&lt;br /&gt;
									}&lt;br /&gt;
									break;&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
							// TODO: What upon a failure?&lt;br /&gt;
							self.open_editor( same_note, cover );&lt;br /&gt;
						},&lt;br /&gt;
						function ( request ) {&lt;br /&gt;
							// TODO: What upon a failure?&lt;br /&gt;
							self.open_editor( same_note, cover );&lt;br /&gt;
						}&lt;br /&gt;
					);&lt;br /&gt;
				} else {&lt;br /&gt;
					this.open_editor( same_note, cover );&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			open_editor: function ( same_note, cover ) {&lt;br /&gt;
				this.editor.hidePreview();&lt;br /&gt;
				if ( !same_note || this.editor.textarea.readOnly ) {&lt;br /&gt;
					// Different note, or save error last time&lt;br /&gt;
					this.editor.setText( this.note.model.wiki );&lt;br /&gt;
				}&lt;br /&gt;
				this.editor.enable( LAPI.Edit.SAVE + LAPI.Edit.PREVIEW + LAPI.Edit.REVERT + LAPI.Edit.CANCEL );&lt;br /&gt;
				this.editor.textarea.readOnly = false;&lt;br /&gt;
				this.editor.textarea.style.backgroundColor = &#039;white&#039;;&lt;br /&gt;
				// Set the position relative to the note&#039;s view.&lt;br /&gt;
				var view_pos = LAPI.Pos.position( this.note.view );&lt;br /&gt;
				var origin = LAPI.Pos.position( cover );&lt;br /&gt;
				this.tooltip.options.fixed_offset.x =&lt;br /&gt;
					view_pos.x - origin.x + this.tooltip.options.mouse_offset.x;&lt;br /&gt;
				this.tooltip.options.fixed_offset.y =&lt;br /&gt;
					view_pos.y - origin.y + this.tooltip.options.mouse_offset.y;&lt;br /&gt;
				this.tooltip.options.fixed_offset.dx = 1;&lt;br /&gt;
				this.tooltip.options.fixed_offset.dy = 1;&lt;br /&gt;
				// Make sure mouse event listeners are removed, especially on IE.&lt;br /&gt;
				this.dim = { x: this.note.view.offsetLeft, y: this.note.view.offsetTop,&lt;br /&gt;
					w: this.note.view.offsetWidth, h: this.note.view.offsetHeight };&lt;br /&gt;
				this.viewer.setShowHideEvents( false );&lt;br /&gt;
				this.viewer.hide(); // Make sure notes are hidden&lt;br /&gt;
				this.viewer.toggle( true ); // Show all note rectangles (but only the dummies)&lt;br /&gt;
				// Now show the editor&lt;br /&gt;
				this.tooltip.show_tip( null, false );&lt;br /&gt;
				var tpos = LAPI.Pos.position( this.editor.textarea );&lt;br /&gt;
				var ppos = LAPI.Pos.position( this.tooltip.popup );&lt;br /&gt;
				tpos = tpos.x - ppos.x;&lt;br /&gt;
				if ( tpos + this.editor.textarea.offsetWidth &amp;gt; this.tooltip.popup.offsetWidth ) { this.editor.textarea.style.width = ( this.tooltip.popup.offsetWidth - 2 * tpos ) + &#039;px&#039;; }&lt;br /&gt;
				if ( LAPI.Browser.is_ie ) {&lt;br /&gt;
					// Fixate textarea width to prevent ugly flicker on each keypress in IE6...&lt;br /&gt;
					this.editor.textarea.style.width = this.editor.textarea.offsetWidth + &#039;px&#039;;&lt;br /&gt;
				}&lt;br /&gt;
				this.visible = true;&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			hide_editor: function ( evt ) {&lt;br /&gt;
				if ( !this.visible ) { return; }&lt;br /&gt;
				this.visible = false;&lt;br /&gt;
				IA.is_editing = false;&lt;br /&gt;
				this.tooltip.hide_now( evt );&lt;br /&gt;
				if ( evt &amp;amp;&amp;amp; evt.type == &#039;keydown&#039; &amp;amp;&amp;amp; !this.saving ) {&lt;br /&gt;
					// ESC pressed on new note before a save attempt&lt;br /&gt;
					this.cancel();&lt;br /&gt;
				}&lt;br /&gt;
				IA.hide_cover();&lt;br /&gt;
				this.viewer.setDefaultMsg();&lt;br /&gt;
				this.viewer.setShowHideEvents( true );&lt;br /&gt;
				this.viewer.hide();&lt;br /&gt;
				this.viewer.show(); // Make sure we get the real views again.&lt;br /&gt;
				// FIXME in Version 2.1: Unfortunately, we don&#039;t have a mouse position here, so sometimes we&lt;br /&gt;
				// may show the note rectangles even though the mouse is now outside the image. (It was&lt;br /&gt;
				// somewhere inside the editor in most cases (if an editor button was clicked), but if ESC was&lt;br /&gt;
				// pressed, it may actually be anywhere.)&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			save: function ( editor ) {&lt;br /&gt;
				var data = editor.getText();&lt;br /&gt;
				if ( !data || !data.length ) {&lt;br /&gt;
					// Empty text&lt;br /&gt;
					if ( this.note.remove() ) {&lt;br /&gt;
						this.hide_editor();&lt;br /&gt;
						this.cancel();&lt;br /&gt;
						this.note = null;&lt;br /&gt;
					} else {&lt;br /&gt;
						this.hide_editor();&lt;br /&gt;
						this.cancel();&lt;br /&gt;
					}&lt;br /&gt;
					return;&lt;br /&gt;
				} else if ( data == this.note.model.wiki ) {&lt;br /&gt;
					// Text unchanged&lt;br /&gt;
					this.hide_editor();&lt;br /&gt;
					this.cancel();&lt;br /&gt;
					return;&lt;br /&gt;
				}&lt;br /&gt;
				// Construct what to insert&lt;br /&gt;
				var dim = Object.clone( this.note.model.dimension );&lt;br /&gt;
				if ( !dim ) {&lt;br /&gt;
					dim = {&lt;br /&gt;
						x: Math.round( this.dim.x * this.viewer.factors.dx ),&lt;br /&gt;
						y: Math.round( this.dim.y * this.viewer.factors.dy ),&lt;br /&gt;
						w: Math.round( this.dim.w * this.viewer.factors.dx ),&lt;br /&gt;
						h: Math.round( this.dim.h * this.viewer.factors.dy )&lt;br /&gt;
					};&lt;br /&gt;
					// Make sure everything is within bounds&lt;br /&gt;
					if ( dim.x + dim.w &amp;gt; this.viewer.full_img.width ) {&lt;br /&gt;
						if ( dim.w &amp;gt; this.dim.w * this.viewer.factors.dx ) {&lt;br /&gt;
							dim.w--;&lt;br /&gt;
							if ( dim.x + dim.w &amp;gt; this.viewer.full_img.width ) {&lt;br /&gt;
								if ( dim.x &amp;gt; 0 ) { dim.x--; } else { dim.w = this.viewer.full_img.width; }&lt;br /&gt;
							}&lt;br /&gt;
						} else {&lt;br /&gt;
							// Width already was rounded down&lt;br /&gt;
							if ( dim.x &amp;gt; 0 ) { dim.x--; }&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
					if ( dim.y + dim.h &amp;gt; this.viewer.full_img.height ) {&lt;br /&gt;
						if ( dim.h &amp;gt; this.dim.h * this.viewer.factors.dy ) {&lt;br /&gt;
							dim.h--;&lt;br /&gt;
							if ( dim.y + dim.h &amp;gt; this.viewer.full_img.height ) {&lt;br /&gt;
								if ( dim.y &amp;gt; 0 ) { dim.y--; } else { dim.h = this.viewer.full_img.height; }&lt;br /&gt;
							}&lt;br /&gt;
						} else {&lt;br /&gt;
							// Height already was rounded down&lt;br /&gt;
							if ( dim.y &amp;gt; 0 ) { dim.y--; }&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
					// If still too large, adjust width and height&lt;br /&gt;
					if ( dim.x + dim.w &amp;gt; this.viewer.full_img.width ) {&lt;br /&gt;
						if ( this.viewer.full_img.width &amp;gt; dim.x ) {&lt;br /&gt;
							dim.w = this.viewer.full_img.width - dim.x;&lt;br /&gt;
						} else {&lt;br /&gt;
							dim.x = this.viewer.full_img.width - 1;&lt;br /&gt;
							dim.w = 1;&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
					if ( dim.y + dim.h &amp;gt; this.viewer.full_img.height ) {&lt;br /&gt;
						if ( this.viewer.full_img.height &amp;gt; dim.y ) {&lt;br /&gt;
							dim.h = this.viewer.full_img.height - dim.y;&lt;br /&gt;
						} else {&lt;br /&gt;
							dim.y = this.viewer.full_img.height - 1;&lt;br /&gt;
							dim.h = 1;&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				this.to_insert =&lt;br /&gt;
					&#039;{{ImageNote&#039; +&lt;br /&gt;
					&#039;|id=&#039; + this.note.model.id +&lt;br /&gt;
					&#039;|x=&#039; + dim.x + &#039;|y=&#039; + dim.y + &#039;|w=&#039; + dim.w + &#039;|h=&#039; + dim.h +&lt;br /&gt;
					&#039;|dimx=&#039; + this.viewer.full_img.width +&lt;br /&gt;
					&#039;|dimy=&#039; + this.viewer.full_img.height +&lt;br /&gt;
					&#039;|style=2&#039; +&lt;br /&gt;
					&#039;}}\n&#039; +&lt;br /&gt;
					data + ( data.endsWith( &#039;\n&#039; ) ? &#039;&#039; : &#039;\n&#039; ) +&lt;br /&gt;
					&#039;{{ImageNoteEnd|id=&#039; + this.note.model.id + &#039;}}&#039;;&lt;br /&gt;
				// Now edit the page&lt;br /&gt;
				var self = this;&lt;br /&gt;
				this.editor.busy( true );&lt;br /&gt;
				this.editor.enable( 0 ); // Disable all buttons&lt;br /&gt;
				this.saving = true;&lt;br /&gt;
				LAPI.Ajax.editPage(&lt;br /&gt;
					mw.config.get( &#039;wgPageName&#039; ),&lt;br /&gt;
					function ( doc, editForm, failureFunc, revision_id ) {&lt;br /&gt;
						try {&lt;br /&gt;
							if ( revision_id &amp;amp;&amp;amp; revision_id != mw.config.get( &#039;wgCurRevisionId&#039; ) ) {&lt;br /&gt;
								// Page was edited since the user loaded it.&lt;br /&gt;
								throw new Error( &#039;#Page version (revision ID) mismatch: edit conflict.&#039; );&lt;br /&gt;
							}&lt;br /&gt;
&lt;br /&gt;
							// Modify the page&lt;br /&gt;
							var textbox = editForm.wpTextbox1;&lt;br /&gt;
							if ( !textbox ) { throw new Error( &#039;#Server replied with invalid edit page.&#039; ); }&lt;br /&gt;
							var pagetext = textbox.value;&lt;br /&gt;
&lt;br /&gt;
							IA.setWikitext( pagetext );&lt;br /&gt;
&lt;br /&gt;
							var span = null;&lt;br /&gt;
							if ( self.note.content ) { // Otherwise it&#039;s a new note!&lt;br /&gt;
								span = IA.findNote( pagetext, self.note.model.id );&lt;br /&gt;
							}&lt;br /&gt;
							if ( span ) { // Replace&lt;br /&gt;
								pagetext =&lt;br /&gt;
									pagetext.substring( 0, span.start ) +&lt;br /&gt;
									self.to_insert +&lt;br /&gt;
									pagetext.substring( span.end );&lt;br /&gt;
							} else { // If not found, append&lt;br /&gt;
								// Try to append right after existing notes&lt;br /&gt;
								var lastNote = pagetext.lastIndexOf( &#039;{{ImageNoteEnd|id=&#039; );&lt;br /&gt;
								if ( lastNote &amp;gt;= 0 ) {&lt;br /&gt;
									var endLastNote = pagetext.substring( lastNote ).indexOf( &#039;}}&#039; );&lt;br /&gt;
									if ( endLastNote &amp;lt; 0 ) {&lt;br /&gt;
										endLastNote = pagetext.substring( lastNote ).indexOf( &#039;\n&#039; );&lt;br /&gt;
										if ( endLastNote &amp;lt; 0 ) { lastNote = -1; } else { lastNote += endLastNote; }&lt;br /&gt;
									} else { lastNote += endLastNote + 2; }&lt;br /&gt;
								}&lt;br /&gt;
								if ( lastNote &amp;gt;= 0 ) {&lt;br /&gt;
									pagetext =&lt;br /&gt;
										pagetext.substring( 0, lastNote ) +&lt;br /&gt;
										&#039;\n&#039; + self.to_insert +&lt;br /&gt;
										pagetext.substring( lastNote );&lt;br /&gt;
								} else { pagetext = pagetext.trimRight() + &#039;\n&#039; + self.to_insert; }&lt;br /&gt;
							}&lt;br /&gt;
							textbox.value = pagetext;&lt;br /&gt;
							var summary = editForm.wpSummary;&lt;br /&gt;
							if ( !summary ) { throw new Error( &#039;#Summary field not found. Check that edit pages have valid XHTML.&#039; ); }&lt;br /&gt;
							// If [[MediaWiki:Copyrightwarning]] is invalid XHTML, we may not have wpSummary!&lt;br /&gt;
							if ( self.note.content != null ) {&lt;br /&gt;
								IA.setSummary(&lt;br /&gt;
									summary,&lt;br /&gt;
									ImageAnnotator.UI.get( &#039;wpImageAnnotatorChangeSummary&#039;, true ) ||&lt;br /&gt;
										&#039;[[MediaWiki talk:Gadget-ImageAnnotator.js|Changing image note]]$1&#039;,&lt;br /&gt;
									data&lt;br /&gt;
								);&lt;br /&gt;
							} else {&lt;br /&gt;
								IA.setSummary(&lt;br /&gt;
									summary,&lt;br /&gt;
									ImageAnnotator.UI.get( &#039;wpImageAnnotatorAddSummary&#039;, true ) ||&lt;br /&gt;
										&#039;[[MediaWiki talk:Gadget-ImageAnnotator.js|Adding image note]]$1&#039;,&lt;br /&gt;
									data&lt;br /&gt;
								);&lt;br /&gt;
							}&lt;br /&gt;
						} catch ( ex ) {&lt;br /&gt;
							failureFunc( null, ex );&lt;br /&gt;
							return;&lt;br /&gt;
						}&lt;br /&gt;
						var edit_page = doc;&lt;br /&gt;
						LAPI.Ajax.submitEdit(&lt;br /&gt;
							editForm,&lt;br /&gt;
							function ( request ) {&lt;br /&gt;
								// After a successful submit.&lt;br /&gt;
								if ( edit_page.isFake &amp;amp;&amp;amp; ( typeof edit_page.dispose === &#039;function&#039; ) ) { edit_page.dispose(); }&lt;br /&gt;
								// TODO: Actually, the edit got through here, so calling failureFunc on&lt;br /&gt;
								// inconsistencies isn&#039;t quite right. Should we reload the page?&lt;br /&gt;
								var id = &#039;image_annotation_content_&#039; + self.note.model.id;&lt;br /&gt;
								var doc = LAPI.Ajax.getHTML( request, failureFunc, id );&lt;br /&gt;
								if ( !doc ) { return; }&lt;br /&gt;
								var html = LAPI.$( id, doc );&lt;br /&gt;
								if ( !html ) {&lt;br /&gt;
									if ( doc.isFake &amp;amp;&amp;amp; ( typeof doc.dispose === &#039;function&#039; ) ) { doc.dispose(); }&lt;br /&gt;
									failureFunc( request, new Error( &#039;#Note not found after saving. Please reload the page.&#039; ) );&lt;br /&gt;
									return;&lt;br /&gt;
								}&lt;br /&gt;
								var revision_id = LAPI.WP.revisionFromHtml( request.responseText );&lt;br /&gt;
								if ( !revision_id ) {&lt;br /&gt;
									if ( doc.isFake &amp;amp;&amp;amp; ( typeof doc.dispose === &#039;function&#039; ) ) { doc.dispose(); }&lt;br /&gt;
									failureFunc( request, new Error( &#039;#Version inconsistency after saving. Please reload the page.&#039; ) );&lt;br /&gt;
									return;&lt;br /&gt;
								}&lt;br /&gt;
								mw.config.set( &#039;wgCurRevisionId&#039;, revision_id ); // Bump revision id!!&lt;br /&gt;
								self.note.model.html = LAPI.DOM.importNode( document, html, true );&lt;br /&gt;
								if ( doc.isFake &amp;amp;&amp;amp; ( typeof doc.dispose === &#039;function&#039; ) ) { doc.dispose(); }&lt;br /&gt;
								self.note.model.dimension = dim; // record dimension&lt;br /&gt;
								self.note.model.html.style.display = &#039;&#039;;&lt;br /&gt;
								self.note.model.wiki = data;&lt;br /&gt;
								self.editor.busy( false );&lt;br /&gt;
								if ( self.note.content ) {&lt;br /&gt;
									LAPI.DOM.removeChildren( self.note.content.main );&lt;br /&gt;
									self.note.content.main.appendChild( self.note.model.html );&lt;br /&gt;
								} else {&lt;br /&gt;
									// New note.&lt;br /&gt;
									self.note.display(); // Actually a misnomer. Just creates &#039;content&#039;.&lt;br /&gt;
									if ( self.viewer.annotations.length &amp;gt; 1 ) {&lt;br /&gt;
										self.viewer.annotations.sort( ImageAnnotation.compare );&lt;br /&gt;
										var idxOfNote = Array.indexOf( self.viewer.annotations, self.note );&lt;br /&gt;
										if ( idxOfNote + 1 &amp;lt; self.viewer.annotations.length ) {&lt;br /&gt;
											LAPI.DOM.insertNode( self.note.view, self.viewer.annotations[ idxOfNote + 1 ].view );&lt;br /&gt;
										}&lt;br /&gt;
									}&lt;br /&gt;
								}&lt;br /&gt;
								self.to_insert = null;&lt;br /&gt;
								self.saving = false;&lt;br /&gt;
								if ( !self.note.tooltip ) { self.note.setTooltip(); }&lt;br /&gt;
								self.hide_editor();&lt;br /&gt;
								IA.is_editing = false;&lt;br /&gt;
								self.editor.setText( data ); // In case the same note is re-opened: start new undo cycle&lt;br /&gt;
							}&lt;br /&gt;
							, function ( request, ex ) {&lt;br /&gt;
								if ( edit_page.isFake &amp;amp;&amp;amp; ( typeof edit_page.dispose === &#039;function&#039; ) ) { edit_page.dispose(); }&lt;br /&gt;
								failureFunc( request, ex );&lt;br /&gt;
							}&lt;br /&gt;
						);&lt;br /&gt;
					},&lt;br /&gt;
					function ( request, ex ) {&lt;br /&gt;
						self.editor.busy( false );&lt;br /&gt;
						self.saving = false;&lt;br /&gt;
						// TODO: How and where to display error if user closed editor through ESC (or through&lt;br /&gt;
						// opening another tooltip) in the meantime?&lt;br /&gt;
						if ( !self.visible ) { return; }&lt;br /&gt;
						// Change the tooltip to show the error.&lt;br /&gt;
						self.editor.setText( self.to_insert );&lt;br /&gt;
						// Error message. Use preview field for this.&lt;br /&gt;
						var error_msg = ImageAnnotator.UI.get( &#039;wpImageAnnotatorSaveError&#039;, false );&lt;br /&gt;
						var lk = getElementsByClassName( error_msg, &#039;span&#039;, &#039;wpImageAnnotatorOwnPageLink&#039; );&lt;br /&gt;
						if ( lk &amp;amp;&amp;amp; lk.length &amp;amp;&amp;amp; lk[ 0 ].firstChild.nodeName.toLowerCase() === &#039;a&#039; ) {&lt;br /&gt;
							lk = lk[ 0 ].firstChild;&lt;br /&gt;
							lk.href = mw.config.get( &#039;wgServer&#039; ) + mw.config.get( &#039;wgArticlePath&#039; ).replace( &#039;$1&#039;, encodeURIComponent( mw.config.get( &#039;wgPageName&#039; ) ) ) + &#039;?action=edit&#039;;&lt;br /&gt;
						}&lt;br /&gt;
						if ( ex ) {&lt;br /&gt;
							var ex_msg = LAPI.formatException( ex, true );&lt;br /&gt;
							if ( ex_msg ) {&lt;br /&gt;
								ex_msg.style.borderBottom = &#039;1px solid red&#039;;&lt;br /&gt;
								var tmp = LAPI.make( &#039;div&#039; );&lt;br /&gt;
								tmp.appendChild( ex_msg );&lt;br /&gt;
								tmp.appendChild( error_msg );&lt;br /&gt;
								error_msg = tmp;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						self.editor.setPreview( error_msg );&lt;br /&gt;
						self.editor.showPreview();&lt;br /&gt;
						self.editor.textarea.readOnly = true;&lt;br /&gt;
						// Force a light gray background, since IE has no visual readonly indication.&lt;br /&gt;
						self.editor.textarea.style.backgroundColor = &#039;#EEEEEE&#039;;&lt;br /&gt;
						self.editor.enable( LAPI.Edit.CANCEL ); // Disable all other buttons&lt;br /&gt;
					}&lt;br /&gt;
				);&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			onpreview: function ( editor ) {&lt;br /&gt;
				if ( this.tooltip ) { this.tooltip.size_change(); }&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			cancel: function ( editor ) {&lt;br /&gt;
				if ( !this.note ) { return; }&lt;br /&gt;
				if ( !this.note.content ) {&lt;br /&gt;
					// No content: Cancel and remove this note!&lt;br /&gt;
					this.note.destroy();&lt;br /&gt;
					this.note = null;&lt;br /&gt;
				}&lt;br /&gt;
				if ( editor ) { this.hide_editor(); }&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			close_tooltip: function ( tooltip, evt ) {&lt;br /&gt;
				this.hide_editor( evt );&lt;br /&gt;
				this.cancel();&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		var ImageNotesViewer = function () { this.initialize.apply( this, arguments ); };&lt;br /&gt;
&lt;br /&gt;
		ImageNotesViewer.prototype = {&lt;br /&gt;
			initialize: function ( descriptor, may_edit ) {&lt;br /&gt;
				Object.merge( descriptor, this );&lt;br /&gt;
				this.annotations = [];&lt;br /&gt;
				this.max_id = 0;&lt;br /&gt;
				this.main_div = null;&lt;br /&gt;
				this.msg = null;&lt;br /&gt;
				this.may_edit = may_edit;&lt;br /&gt;
				this.setup_done = false;&lt;br /&gt;
				this.tip = null;&lt;br /&gt;
				this.icon = null;&lt;br /&gt;
				this.factors = {&lt;br /&gt;
					dx: this.full_img.width / this.thumb.width,&lt;br /&gt;
					dy: this.full_img.height / this.thumb.height&lt;br /&gt;
				};&lt;br /&gt;
&lt;br /&gt;
				if ( !this.isThumbnail &amp;amp;&amp;amp; !this.isOther ) {&lt;br /&gt;
					this.setup();&lt;br /&gt;
				} else {&lt;br /&gt;
					// Normalize the namespace of the realName to &#039;File&#039; to account for images possibly stored at&lt;br /&gt;
					// a foreign repository (the Commons). Otherwise a later information load might fail because&lt;br /&gt;
					// the link is local and might actually be given as &amp;quot;Bild:Foo.jpg&amp;quot;. If that page doesn&#039;t exist&lt;br /&gt;
					// locally, we want to ask at the Commons about &amp;quot;File:Foo.jpg&amp;quot;. The Commons doesn&#039;t understand&lt;br /&gt;
					// the localized namespace names of other wikis, but the canonical namespace name &#039;File&#039; works&lt;br /&gt;
					// also locally.&lt;br /&gt;
					this.realName = &#039;File:&#039; + this.realName.substring( this.realName.indexOf( &#039;:&#039; ) + 1 );&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			setup: function ( onlyIcon ) {&lt;br /&gt;
				this.setup_done = true;&lt;br /&gt;
				var name = this.realName;&lt;br /&gt;
				if ( this.isThumbnail || this.scope == document || this.may_edit || !IA.haveAjax ) {&lt;br /&gt;
					this.imgName = this.realName;&lt;br /&gt;
					this.realName = &#039;&#039;;&lt;br /&gt;
				} else {&lt;br /&gt;
					name = getElementsByClassName( this.scope, &#039;*&#039;, &#039;wpImageAnnotatorFullName&#039; );&lt;br /&gt;
					this.realName = ( ( name &amp;amp;&amp;amp; name.length ) ? LAPI.DOM.getInnerText( name[ 0 ] ) : &#039;&#039; );&lt;br /&gt;
					this.imgName = this.realName;&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				var annotations = getElementsByClassName( this.scope, &#039;div&#039;, IA.annotation_class );&lt;br /&gt;
&lt;br /&gt;
				if ( !this.may_edit &amp;amp;&amp;amp; ( !annotations || annotations.length === 0 ) ) { return; } // Nothing to do&lt;br /&gt;
&lt;br /&gt;
				// A div inserted around the image. It ensures that everything we add is positioned properly&lt;br /&gt;
				// over the image, even if the browser window size changes and re-layouts occur.&lt;br /&gt;
				var isEnabledImage = LAPI.DOM.hasClass( this.scope, &#039;wpImageAnnotatorEnable&#039; );&lt;br /&gt;
				if ( !this.isThumbnail &amp;amp;&amp;amp; !this.isOther &amp;amp;&amp;amp; !isEnabledImage ) {&lt;br /&gt;
					this.img_div = LAPI.make( &#039;div&#039;, null, { position: &#039;relative&#039;, width: String( this.thumb.width ) + &#039;px&#039; } );&lt;br /&gt;
					var floater = LAPI.make(&lt;br /&gt;
						&#039;div&#039;, null,&lt;br /&gt;
						{&lt;br /&gt;
							cssFloat: ( IA.is_rtl ? &#039;right&#039; : &#039;left&#039; ),&lt;br /&gt;
							styleFloat: ( IA.is_rtl ? &#039;right&#039; : &#039;left&#039; ), // For IE...&lt;br /&gt;
							width: String( this.thumb.width ) + &#039;px&#039;,&lt;br /&gt;
							position: &#039;relative&#039; // Fixes IE layout bugs...&lt;br /&gt;
						}&lt;br /&gt;
					);&lt;br /&gt;
					floater.appendChild( this.img_div );&lt;br /&gt;
					this.img.parentNode.parentNode.insertBefore( floater, this.img.parentNode );&lt;br /&gt;
					this.img_div.appendChild( this.img.parentNode );&lt;br /&gt;
					// And now a clear:left to make the rest appear below the image, as usual.&lt;br /&gt;
					var breaker = LAPI.make( &#039;div&#039;, null, { clear: ( IA.is_rtl ? &#039;right&#039; : &#039;left&#039; ) } );&lt;br /&gt;
					LAPI.DOM.insertAfter( breaker, floater );&lt;br /&gt;
					// Remove spurious br tag.&lt;br /&gt;
					if ( breaker.nextSibling &amp;amp;&amp;amp; breaker.nextSibling.nodeName.toLowerCase() == &#039;br&#039; ) { LAPI.DOM.removeNode( breaker.nextSibling ); }&lt;br /&gt;
				} else if ( this.isOther || isEnabledImage ) {&lt;br /&gt;
					this.img_div = LAPI.make( &#039;div&#039;, null, { position: &#039;relative&#039;, width: String( this.thumb.width ) + &#039;px&#039; } );&lt;br /&gt;
					this.img.parentNode.parentNode.insertBefore( this.img_div, this.img.parentNode );&lt;br /&gt;
					this.img_div.appendChild( this.img.parentNode );&lt;br /&gt;
					// Insert one more to have a file_div, so that we can align the message text correctly&lt;br /&gt;
					this.file_div = LAPI.make( &#039;div&#039;, null, { width: String( this.thumb.width ) + &#039;px&#039; } );&lt;br /&gt;
					this.img_div.parentNode.insertBefore( this.file_div, this.img_div );&lt;br /&gt;
					this.file_div.appendChild( this.img_div );&lt;br /&gt;
				} else { // Thumbnail&lt;br /&gt;
					this.img_div = LAPI.make(&lt;br /&gt;
						&#039;div&#039;,&lt;br /&gt;
						{ className: &#039;thumbimage&#039; },&lt;br /&gt;
						{ position: &#039;relative&#039;, width: String( this.thumb.width ) + &#039;px&#039; }&lt;br /&gt;
					);&lt;br /&gt;
					this.img.parentNode.parentNode.insertBefore( this.img_div, this.img.parentNode );&lt;br /&gt;
					this.img.style.border = &#039;none&#039;;&lt;br /&gt;
					this.img_div.appendChild( this.img.parentNode );&lt;br /&gt;
				}&lt;br /&gt;
				if (&lt;br /&gt;
					( this.isThumbnail || this.isOther ) &amp;amp;&amp;amp; !this.may_edit &amp;amp;&amp;amp;&lt;br /&gt;
					(&lt;br /&gt;
						onlyIcon ||&lt;br /&gt;
						this.iconOnly ||&lt;br /&gt;
						ImageAnnotator_config.inlineImageUsesIndicator(&lt;br /&gt;
							name, this.isLocal, this.thumb, this.full_img, annotations.length, this.isThumbnail&lt;br /&gt;
						)&lt;br /&gt;
					)&lt;br /&gt;
				) {&lt;br /&gt;
					// Use an onclick handler instead of a link around the image. The link may have a default white&lt;br /&gt;
					// background, but we want to be sure to have transparency. The image should be an 8-bit indexed&lt;br /&gt;
					// PNG or a GIF and have a transparent background.&lt;br /&gt;
					this.icon = ImageAnnotator.UI.get( &#039;wpImageAnnotatorIndicatorIcon&#039;, false );&lt;br /&gt;
					if ( this.icon ) { this.icon = this.icon.firstChild; } // Skip the message container span or div&lt;br /&gt;
					// Guard against misconfigurations&lt;br /&gt;
					if (&lt;br /&gt;
						this.icon &amp;amp;&amp;amp;&lt;br /&gt;
						this.icon.nodeName.toLowerCase() == &#039;a&#039; &amp;amp;&amp;amp;&lt;br /&gt;
						this.icon.firstChild.nodeName.toLowerCase() == &#039;img&#039;&lt;br /&gt;
					) {&lt;br /&gt;
						// Make sure we use the right protocol:&lt;br /&gt;
						var srcFixed = this.icon.firstChild.getAttribute( &#039;src&#039;, 2 ).replace( /^https?:/, document.location.protocol );&lt;br /&gt;
						this.icon.firstChild.src = srcFixed;&lt;br /&gt;
						this.icon.firstChild.title = this.icon.title;&lt;br /&gt;
						this.icon = this.icon.firstChild;&lt;br /&gt;
					} else if ( !this.icon || this.icon.nodeName.toLowerCase() !== &#039;img&#039; ) {&lt;br /&gt;
						this.icon = LAPI.DOM.makeImage(&lt;br /&gt;
							IA.indication_icon,&lt;br /&gt;
							14, 14,&lt;br /&gt;
							ImageAnnotator.UI.get( &#039;wpImageAnnotatorHasNotesMsg&#039;, true ) || &#039;&#039;&lt;br /&gt;
						);&lt;br /&gt;
					}&lt;br /&gt;
					Object.merge(&lt;br /&gt;
						{ position: &#039;absolute&#039;, zIndex: 1000, top: &#039;0px&#039;, cursor: &#039;pointer&#039; }&lt;br /&gt;
						, this.icon.style&lt;br /&gt;
					);&lt;br /&gt;
					this.icon.onclick = ( function () { location.href = this.img.parentNode.href; } ).bind( this );&lt;br /&gt;
					if ( IA.is_rtl ) { this.icon.style.right = &#039;0px&#039;; } else { this.icon.style.left = &#039;0px&#039;; }&lt;br /&gt;
					this.img_div.appendChild( this.icon );&lt;br /&gt;
					// And done. We just show the icon, no fancy event handling needed.&lt;br /&gt;
					return;&lt;br /&gt;
				}&lt;br /&gt;
				// Set colors&lt;br /&gt;
				var colors = IA.getRawItem( &#039;colors&#039;, this.scope );&lt;br /&gt;
				this.outer_border =&lt;br /&gt;
					colors &amp;amp;&amp;amp; IA.getItem( &#039;outer&#039;, colors ) || IA.outer_border;&lt;br /&gt;
				this.inner_border =&lt;br /&gt;
					colors &amp;amp;&amp;amp; IA.getItem( &#039;inner&#039;, colors ) || IA.inner_border;&lt;br /&gt;
				this.active_border =&lt;br /&gt;
					colors &amp;amp;&amp;amp; IA.getItem( &#039;active&#039;, colors ) || IA.active_border;&lt;br /&gt;
				if ( annotations ) {&lt;br /&gt;
					for ( var i = 0; i &amp;lt; annotations.length; i++ ) {&lt;br /&gt;
						var id = annotations[ i ].id;&lt;br /&gt;
						if ( id &amp;amp;&amp;amp; /^image_annotation_note_(\d+)$/.test( id ) ) {&lt;br /&gt;
							id = parseInt( id.substring( &#039;image_annotation_note_&#039;.length ) );&lt;br /&gt;
						} else { id = null; }&lt;br /&gt;
						if ( id ) {&lt;br /&gt;
							if ( id &amp;gt; this.max_id ) { this.max_id = id; }&lt;br /&gt;
							var w = IA.getIntItem( &#039;full_width_&#039; + id, this.scope );&lt;br /&gt;
							var h = IA.getIntItem( &#039;full_height_&#039; + id, this.scope );&lt;br /&gt;
							if (&lt;br /&gt;
								w == this.full_img.width &amp;amp;&amp;amp; h == this.full_img.height &amp;amp;&amp;amp;&lt;br /&gt;
								!Array.exists( this.annotations, function ( note ) { return note.model.id == id; } )&lt;br /&gt;
							) {&lt;br /&gt;
								try {&lt;br /&gt;
									this.register( new ImageAnnotation( annotations[ i ], this, id ) );&lt;br /&gt;
								} catch ( ex ) {&lt;br /&gt;
									// Swallow.&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				if ( this.annotations.length &amp;gt; 1 ) { this.annotations.sort( ImageAnnotation.compare ); }&lt;br /&gt;
				// Add the rectangles of existing notes to the DOM now that they are sorted.&lt;br /&gt;
				Array.forEach( this.annotations, ( function ( note ) { this.img_div.appendChild( note.view ); } ).bind( this ) );&lt;br /&gt;
				if ( this.isThumbnail ) {&lt;br /&gt;
					this.main_div = getElementsByClassName( this.file_div, &#039;div&#039;, &#039;thumbcaption&#039; );&lt;br /&gt;
					if ( !this.main_div || this.main_div.length == 0 ) { this.main_div = null; } else { this.main_div = this.main_div[ 0 ]; }&lt;br /&gt;
				}&lt;br /&gt;
				if ( !this.main_div ) {&lt;br /&gt;
					this.main_div = LAPI.make( &#039;div&#039; );&lt;br /&gt;
					if ( IA.is_rtl ) {&lt;br /&gt;
						this.main_div.style.direction = &#039;rtl&#039;;&lt;br /&gt;
						this.main_div.style.textAlign = &#039;right&#039;;&lt;br /&gt;
						this.main_div.className = &#039;rtl&#039;;&lt;br /&gt;
					} else {&lt;br /&gt;
						this.main_div.style.textAlign = &#039;left&#039;;&lt;br /&gt;
					}&lt;br /&gt;
					if ( !this.isThumbnail &amp;amp;&amp;amp; !this.isOther &amp;amp;&amp;amp; !isEnabledImage ) {&lt;br /&gt;
						LAPI.DOM.insertAfter( this.main_div, this.file_div );&lt;br /&gt;
					} else {&lt;br /&gt;
						LAPI.DOM.insertAfter( this.main_div, this.img_div );&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				if (&lt;br /&gt;
					!( this.isThumbnail || this.isOther ) ||&lt;br /&gt;
					!this.noCaption &amp;amp;&amp;amp;&lt;br /&gt;
					!IA.hideCaptions &amp;amp;&amp;amp;&lt;br /&gt;
					ImageAnnotator_config.displayCaptionInArticles(&lt;br /&gt;
						name, this.isLocal, this.thumb, this.full_img, annotations.length, this.isThumbnail&lt;br /&gt;
					)&lt;br /&gt;
				) {&lt;br /&gt;
					this.msg = LAPI.make( &#039;div&#039;, null, { display: &#039;none&#039; } );&lt;br /&gt;
					if ( IA.is_rtl ) {&lt;br /&gt;
						this.msg.style.direction = &#039;rtl&#039;;&lt;br /&gt;
						this.msg.className = &#039;rtl&#039;;&lt;br /&gt;
					}&lt;br /&gt;
					if ( this.isThumbnail ) { this.msg.style.fontSize = &#039;90%&#039;; }&lt;br /&gt;
					this.main_div.appendChild( this.msg );&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				// Set overflow parents, if any&lt;br /&gt;
&lt;br /&gt;
				var simple = !!window.getComputedStyle;&lt;br /&gt;
				var checks = ( simple ? [ &#039;overflow&#039;, &#039;overflow-x&#039;, &#039;overflow-y&#039; ] :&lt;br /&gt;
					[ &#039;overflow&#039;, &#039;overflowX&#039;, &#039;overflowY&#039; ]&lt;br /&gt;
				);&lt;br /&gt;
				var curStyle = null;&lt;br /&gt;
				for ( var up = this.img.parentNode.parentNode; up != document.body; up = up.parentNode ) {&lt;br /&gt;
					curStyle = ( simple ? window.getComputedStyle( up, null ) : ( up.currentStyle || up.style ) );&lt;br /&gt;
					// &amp;quot;up.style&amp;quot; is actually incorrect, but a best-effort fallback.&lt;br /&gt;
					var overflow = Array.any( checks, function ( t ) {&lt;br /&gt;
						var o = curStyle[ t ];&lt;br /&gt;
						return ( o &amp;amp;&amp;amp; o != &#039;visible&#039; ) ? o : null;&lt;br /&gt;
					} );&lt;br /&gt;
					if ( overflow ) {&lt;br /&gt;
						if ( !this.overflowParents ) { this.overflowParents = [ up ]; } else { this.overflowParents[ this.overflowParents.length ] = up; }&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				if ( this.overflowParents &amp;amp;&amp;amp; this.may_edit ) {&lt;br /&gt;
					// Forbid editing if we have such a crazy layout.&lt;br /&gt;
					this.may_edit = false;&lt;br /&gt;
					IA.may_edit = false;&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				this.show_evt = LAPI.Evt.makeListener( this, this.show );&lt;br /&gt;
				if ( this.overflowParents || LAPI.Browser.is_ie ) {&lt;br /&gt;
					// If we have overflowParents, also use a mousemove listener to show/hide the whole&lt;br /&gt;
					// view (FF doesn&#039;t send mouseout events if the visible border is still within the image, i.e.,&lt;br /&gt;
					// if not the whole image is visible). On IE, also use this handler to show/hide the notes&lt;br /&gt;
					// if we&#039;re still within the visible area of the image. IE passes through mouse_over events to&lt;br /&gt;
					// the img even if the mouse is within a note&#039;s rectangle. Apparently is doesn&#039;t handle&lt;br /&gt;
					// transparent divs correctly. As a result, the notes will pop up and disappear only when the&lt;br /&gt;
					// mouse crosses the border, and if one moves the mouse a little fast across the border, we&lt;br /&gt;
					// don&#039;t get any event at all. That&#039;s no good.&lt;br /&gt;
					this.move_evt = LAPI.Evt.makeListener( this, this.check_hide );&lt;br /&gt;
				} else { this.hide_evt = LAPI.Evt.makeListener( this, this.hide ); }&lt;br /&gt;
				this.move_listening = false;&lt;br /&gt;
				this.setShowHideEvents( true );&lt;br /&gt;
				this.visible = false;&lt;br /&gt;
				this.setDefaultMsg();&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			cannotEdit: function () {&lt;br /&gt;
				if ( !this.may_edit ) { return; }&lt;br /&gt;
				this.may_edit = false;&lt;br /&gt;
				Array.forEach( this.annotations, function ( note ) { note.cannotEdit(); } );&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			setShowHideEvents: function ( set ) {&lt;br /&gt;
				if ( this.icon ) { return; }&lt;br /&gt;
				if ( set ) {&lt;br /&gt;
					LAPI.Evt.attach( this.img, IA.mouse_in, this.show_evt );&lt;br /&gt;
					if ( this.hide_evt ) { LAPI.Evt.attach( this.img, IA.mouse_out, this.hide_evt ); }&lt;br /&gt;
				} else {&lt;br /&gt;
					LAPI.Evt.remove( this.img, IA.mouse_in, this.show_evt );&lt;br /&gt;
					if ( this.hide_evt ) {&lt;br /&gt;
						LAPI.Evt.remove( this.img, IA.mouse_out, this.hide_evt );&lt;br /&gt;
					} else if ( this.move_listening ) { this.removeMoveListener(); }&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			removeMoveListener: function () {&lt;br /&gt;
				if ( this.icon ) { return; }&lt;br /&gt;
				this.move_listening = false;&lt;br /&gt;
				if ( this.move_evt ) {&lt;br /&gt;
					if ( !LAPI.Browser.is_ie &amp;amp;&amp;amp; typeof document.captureEvents === &#039;function&#039; ) { document.captureEvents( null ); }&lt;br /&gt;
					LAPI.Evt.remove( document, &#039;mousemove&#039;, this.move_evt, true );&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			adjustRectangleSize: function ( node ) {&lt;br /&gt;
				if ( this.icon ) { return; }&lt;br /&gt;
				// Make sure the note boxes don&#039;t overlap the image boundary; we might get an event&lt;br /&gt;
				// loop otherwise if the mouse was just on that overlapped boundary, resulting in flickering.&lt;br /&gt;
				var view_x = node.offsetLeft;&lt;br /&gt;
				var view_y = node.offsetTop;&lt;br /&gt;
				var view_w = node.offsetWidth;&lt;br /&gt;
				var view_h = node.offsetHeight;&lt;br /&gt;
				if ( view_x === 0 ) { view_x = 1; }&lt;br /&gt;
				if ( view_y === 0 ) { view_y = 1; }&lt;br /&gt;
				if ( view_x + view_w &amp;gt;= this.thumb.width ) {&lt;br /&gt;
					view_w = this.thumb.width - view_x - 1;&lt;br /&gt;
					if ( view_w &amp;lt;= 4 ) { view_w = 4; view_x = this.thumb.width - view_w - 1; }&lt;br /&gt;
				}&lt;br /&gt;
				if ( view_y + view_h &amp;gt;= this.thumb.height ) {&lt;br /&gt;
					view_h = this.thumb.height - view_y - 1;&lt;br /&gt;
					if ( view_h &amp;lt;= 4 ) { view_h = 4; view_y = this.thumb.height - view_h - 1; }&lt;br /&gt;
				}&lt;br /&gt;
				// Now set position and width and height, subtracting cumulated border widths&lt;br /&gt;
				if (&lt;br /&gt;
					view_x != node.offsetLeft || view_y != node.offsetTop ||&lt;br /&gt;
					view_w != node.offsetWidth || view_h != node.offsetHeight&lt;br /&gt;
				) {&lt;br /&gt;
					node.style.top = String( view_y ) + &#039;px&#039;;&lt;br /&gt;
					node.style.left = String( view_x ) + &#039;px&#039;;&lt;br /&gt;
					node.style.width = String( view_w - 2 ) + &#039;px&#039;;&lt;br /&gt;
					node.style.height = String( view_h - 2 ) + &#039;px&#039;;&lt;br /&gt;
					node.firstChild.style.width = String( view_w - 4 ) + &#039;px&#039;;&lt;br /&gt;
					node.firstChild.style.height = String( view_h - 4 ) + &#039;px&#039;;&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			toggle: function ( dummies ) {&lt;br /&gt;
				var i;&lt;br /&gt;
				if ( !this.annotations || this.annotations.length === 0 || this.icon ) { return; }&lt;br /&gt;
				if ( dummies ) {&lt;br /&gt;
					for ( i = 0; i &amp;lt; this.annotations.length; i++ ) {&lt;br /&gt;
						this.annotations[ i ].view.style.display = &#039;none&#039;;&lt;br /&gt;
						if ( this.visible &amp;amp;&amp;amp; this.annotations[ i ].tooltip ) { this.annotations[ i ].tooltip.hide_now( null ); }&lt;br /&gt;
						this.annotations[ i ].dummy.style.display = ( this.visible ? &#039;none&#039; : &#039;&#039; );&lt;br /&gt;
						if ( !this.visible ) { this.adjustRectangleSize( this.annotations[ i ].dummy ); }&lt;br /&gt;
					}&lt;br /&gt;
				} else {&lt;br /&gt;
					for ( i = 0; i &amp;lt; this.annotations.length; i++ ) {&lt;br /&gt;
						this.annotations[ i ].dummy.style.display = &#039;none&#039;;&lt;br /&gt;
						this.annotations[ i ].view.style.display = ( this.visible ? &#039;none&#039; : &#039;&#039; );&lt;br /&gt;
						if ( !this.visible ) { this.adjustRectangleSize( this.annotations[ i ].view ); }&lt;br /&gt;
						if ( this.visible &amp;amp;&amp;amp; this.annotations[ i ].tooltip ) { this.annotations[ i ].tooltip.hide_now( null ); }&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				this.visible = !this.visible;&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			show: function ( evt ) {&lt;br /&gt;
				if ( this.visible || this.icon ) { return; }&lt;br /&gt;
				this.toggle( IA.is_adding || IA.is_editing );&lt;br /&gt;
				if ( this.move_evt &amp;amp;&amp;amp; !this.move_listening ) {&lt;br /&gt;
					LAPI.Evt.attach( document, &#039;mousemove&#039;, this.move_evt, true );&lt;br /&gt;
					this.move_listening = true;&lt;br /&gt;
					if ( !LAPI.Browser.is_ie &amp;amp;&amp;amp; typeof document.captureEvents === &#039;function&#039; ) { document.captureEvents( Event.MOUSEMOVE ); }&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			hide: function ( evt ) {&lt;br /&gt;
				if ( this.icon ) { return true; }&lt;br /&gt;
				if ( !this.visible ) {&lt;br /&gt;
					// Huh?&lt;br /&gt;
					if ( this.move_listening ) { this.removeMoveListener(); }&lt;br /&gt;
					return true;&lt;br /&gt;
				}&lt;br /&gt;
				if ( evt ) {&lt;br /&gt;
					var mouse_pos = LAPI.Pos.mousePosition( evt );&lt;br /&gt;
					if ( mouse_pos ) {&lt;br /&gt;
						if ( this.tip ) {&lt;br /&gt;
							// Check whether we&#039;re within the visible note.&lt;br /&gt;
							if ( LAPI.Pos.isWithin( this.tip.popup, mouse_pos.x, mouse_pos.y ) ) { return true; }&lt;br /&gt;
						}&lt;br /&gt;
						var is_within = true;&lt;br /&gt;
						var img_pos = LAPI.Pos.position( this.img );&lt;br /&gt;
						var rect = {&lt;br /&gt;
							x: img_pos.x,&lt;br /&gt;
							y: img_pos.y,&lt;br /&gt;
							r: ( img_pos.x + this.img.offsetWidth ),&lt;br /&gt;
							b: ( img_pos.y + this.img.offsetHeight )&lt;br /&gt;
						};&lt;br /&gt;
						var i;&lt;br /&gt;
						if ( this.overflowParents ) {&lt;br /&gt;
							// We&#039;re within some elements having overflow:hidden or overflow:auto or overflow:scroll set.&lt;br /&gt;
							// Compute the actually visible region by intersecting the rectangle given by img_pos and&lt;br /&gt;
							// this.img.offsetWidth, this.img.offsetTop with the rectangles of all overflow parents.&lt;br /&gt;
&lt;br /&gt;
							function intersect_rectangles( a, b ) {&lt;br /&gt;
								if ( b.x &amp;gt; a.r || b.r &amp;lt; a.x || b.y &amp;gt; a.b || b.b &amp;lt; a.y ) { return { x: 0, y: 0, r: 0, b: 0 }; }&lt;br /&gt;
&lt;br /&gt;
								return {&lt;br /&gt;
									x: Math.max( a.x, b.x ),&lt;br /&gt;
									y: Math.max( a.y, b.y ),&lt;br /&gt;
									r: Math.min( a.r, b.r ),&lt;br /&gt;
									b: Math.min( a.b, b.b )&lt;br /&gt;
								};&lt;br /&gt;
							}&lt;br /&gt;
&lt;br /&gt;
							for ( i = 0; i &amp;lt; this.overflowParents.length &amp;amp;&amp;amp; rect.x &amp;lt; rect.r &amp;amp;&amp;amp; rect.y &amp;lt; rect.b; i++ ) {&lt;br /&gt;
								img_pos = LAPI.Pos.position( this.overflowParents[ i ] );&lt;br /&gt;
								img_pos.r = img_pos.x + this.overflowParents[ i ].clientWidth;&lt;br /&gt;
								img_pos.b = img_pos.y + this.overflowParents[ i ].clientHeight;&lt;br /&gt;
								rect = intersect_rectangles( rect, img_pos );&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
						is_within = !( rect.x &amp;gt;= rect.r || rect.y &amp;gt;= rect.b || // Empty rectangle&lt;br /&gt;
							rect.x &amp;gt;= mouse_pos.x || rect.r &amp;lt;= mouse_pos.x ||&lt;br /&gt;
							rect.y &amp;gt;= mouse_pos.y || rect.b &amp;lt;= mouse_pos.y&lt;br /&gt;
						);&lt;br /&gt;
						if ( is_within ) {&lt;br /&gt;
							if ( LAPI.Browser.is_ie &amp;amp;&amp;amp; evt.type === &#039;mousemove&#039; ) {&lt;br /&gt;
								var display;&lt;br /&gt;
								// Loop in reverse order to properly display top rectangle&#039;s note!&lt;br /&gt;
								for ( i = this.annotations.length - 1; i &amp;gt;= 0; i-- ) {&lt;br /&gt;
									display = this.annotations[ i ].view.style.display;&lt;br /&gt;
									if (&lt;br /&gt;
										display !== &#039;none&#039; &amp;amp;&amp;amp; display != null &amp;amp;&amp;amp;&lt;br /&gt;
										LAPI.Pos.isWithin( this.annotations[ i ].view.firstChild, mouse_pos.x, mouse_pos.y )&lt;br /&gt;
									) {&lt;br /&gt;
										if ( !this.annotations[ i ].tooltip.visible ) { this.annotations[ i ].tooltip.show( evt ); }&lt;br /&gt;
										return true;&lt;br /&gt;
									}&lt;br /&gt;
								}&lt;br /&gt;
								if ( this.tip ) { this.tip.hide_now(); } // Inside the image, but not within any note rectangle&lt;br /&gt;
							}&lt;br /&gt;
							return true;&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				// Not within the image, or forced hiding (no event)&lt;br /&gt;
				if ( this.move_listening ) { this.removeMoveListener(); }&lt;br /&gt;
				this.toggle( IA.is_adding || IA.is_editing );&lt;br /&gt;
				return true;&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			check_hide: function ( evt ) {&lt;br /&gt;
				if ( this.icon ) { return true; }&lt;br /&gt;
				if ( this.visible ) { this.hide( evt ); }&lt;br /&gt;
				return true;&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			register: function ( new_note ) {&lt;br /&gt;
				this.annotations[ this.annotations.length ] = new_note;&lt;br /&gt;
				if ( new_note.model.id &amp;gt; 0 ) {&lt;br /&gt;
					if ( new_note.model.id &amp;gt; this.max_id ) { this.max_id = new_note.model.id; }&lt;br /&gt;
				} else {&lt;br /&gt;
					new_note.model.id = ++this.max_id;&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			deregister: function ( note ) {&lt;br /&gt;
				Array.remove( this.annotations, note );&lt;br /&gt;
				if ( note.model.id == this.max_id ) { this.max_id--; }&lt;br /&gt;
				if ( this.annotations.length === 0 ) { this.setDefaultMsg(); } // If we removed the last one, clear the msg&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			setDefaultMsg: function () {&lt;br /&gt;
				if ( this.annotations &amp;amp;&amp;amp; this.annotations.length &amp;amp;&amp;amp; this.msg ) {&lt;br /&gt;
					LAPI.DOM.removeChildren( this.msg );&lt;br /&gt;
					this.msg.appendChild( ImageAnnotator.UI.get( &#039;wpImageAnnotatorHasNotesMsg&#039;, false ) );&lt;br /&gt;
					if ( this.realName &amp;amp;&amp;amp; typeof this.realName === &#039;string&#039; &amp;amp;&amp;amp; this.realName.length ) {&lt;br /&gt;
						var otherPageMsg = ImageAnnotator.UI.get( &#039;wpImageAnnotatorEditNotesMsg&#039;, false );&lt;br /&gt;
						if ( otherPageMsg ) {&lt;br /&gt;
							var lk = otherPageMsg.getElementsByTagName( &#039;a&#039; );&lt;br /&gt;
							if ( lk &amp;amp;&amp;amp; lk.length ) {&lt;br /&gt;
								lk = lk[ 0 ];&lt;br /&gt;
								lk.parentNode.replaceChild(&lt;br /&gt;
									LAPI.DOM.makeLink(&lt;br /&gt;
										mw.config.get( &#039;wgArticlePath&#039; ).replace( &#039;$1&#039;, encodeURIComponent( this.realName ) ),&lt;br /&gt;
										this.realName,&lt;br /&gt;
										this.realName&lt;br /&gt;
									),&lt;br /&gt;
									lk&lt;br /&gt;
								);&lt;br /&gt;
								this.msg.appendChild( otherPageMsg );&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
					this.msg.style.display = &#039;&#039;;&lt;br /&gt;
				} else {&lt;br /&gt;
					if ( this.msg ) { this.msg.style.display = &#039;none&#039;; }&lt;br /&gt;
				}&lt;br /&gt;
				if ( IA.button_div &amp;amp;&amp;amp; this.may_edit ) { IA.button_div.style.display = &#039;&#039;; }&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		var IA = {&lt;br /&gt;
			// This object is responsible for setting up annotations when a page is loaded. It loads all&lt;br /&gt;
			// annotations in the page source, and adds an &amp;quot;Annotate this image&amp;quot; button plus the support&lt;br /&gt;
			// for drawing rectangles onto the image if there is only one image and editing is allowed.&lt;br /&gt;
&lt;br /&gt;
			haveAjax: false,&lt;br /&gt;
&lt;br /&gt;
			button_div: null,&lt;br /&gt;
			add_button: null,&lt;br /&gt;
&lt;br /&gt;
			cover: null,&lt;br /&gt;
			border: null,&lt;br /&gt;
			definer: null,&lt;br /&gt;
&lt;br /&gt;
			mouse_in: ( window.ActiveXObject ? &#039;mouseenter&#039; : &#039;mouseover&#039; ),&lt;br /&gt;
			mouse_out: ( window.ActiveXObject ? &#039;mouseleave&#039; : &#039;mouseout&#039; ),&lt;br /&gt;
&lt;br /&gt;
			annotation_class: &#039;image_annotation&#039;,&lt;br /&gt;
&lt;br /&gt;
			// Format of notes in Wikitext. Note: there are two formats, an old one and a new one.&lt;br /&gt;
			// We only write the newest (last) one, but we can read also the older formats. Order is&lt;br /&gt;
			// important, because the old format also used the ImageNote template, but for a different&lt;br /&gt;
			// purpose.&lt;br /&gt;
			note_delim: [&lt;br /&gt;
				{&lt;br /&gt;
					start: &#039;&amp;lt;div id=&amp;quot;image_annotation_note_$1&amp;quot;&#039;,&lt;br /&gt;
					end: &#039;&amp;lt;/div&amp;gt;&amp;lt;!-- End of annotation $1--&amp;gt;&#039;,&lt;br /&gt;
					content_start: &#039;&amp;lt;div id=&amp;quot;image_annotation_content_$1&amp;quot;&amp;gt;\n&#039;,&lt;br /&gt;
					content_end: &#039;&amp;lt;/div&amp;gt;\n&amp;lt;span id=&amp;quot;image_annotation_wikitext_$1&amp;quot;&#039;&lt;br /&gt;
				},&lt;br /&gt;
				{&lt;br /&gt;
					start: &#039;{{ImageNote|id=$1&#039;,&lt;br /&gt;
					end: &#039;{{ImageNoteEnd|id=$1}}&#039;,&lt;br /&gt;
					content_start: &#039;}}\n&#039;,&lt;br /&gt;
					content_end: &#039;{{ImageNoteEnd|id=$1}}&#039;&lt;br /&gt;
				}&lt;br /&gt;
			],&lt;br /&gt;
&lt;br /&gt;
			tooltip_styles: { // The style for all our tooltips&lt;br /&gt;
				border: &#039;1px solid #8888aa&#039;,&lt;br /&gt;
				backgroundColor: &#039;#ffffe0&#039;,&lt;br /&gt;
				padding: &#039;0.3em&#039;,&lt;br /&gt;
				fontSize: ( ( mw.config.get( &#039;skin&#039; ) == &#039;monobook&#039; || mw.config.get( &#039;skin&#039; ) == &#039;modern&#039; ) ? &#039;127%&#039; : &#039;100%&#039; )&lt;br /&gt;
				// Scale up to default text size&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			editor: null,&lt;br /&gt;
&lt;br /&gt;
			wiki_read: false,&lt;br /&gt;
			is_rtl: false,&lt;br /&gt;
&lt;br /&gt;
			move_listening: false,&lt;br /&gt;
			is_tracking: false,&lt;br /&gt;
			is_adding: false,&lt;br /&gt;
			is_editing: false,&lt;br /&gt;
&lt;br /&gt;
			zoom_threshold: 8.0,&lt;br /&gt;
			zoom_factor: 4.0,&lt;br /&gt;
&lt;br /&gt;
			install_attempts: 0,&lt;br /&gt;
			max_install_attempts: 10, // Maximum 5 seconds&lt;br /&gt;
&lt;br /&gt;
			imgs_with_notes: [],&lt;br /&gt;
			thumbs: [],&lt;br /&gt;
			other_images: [],&lt;br /&gt;
&lt;br /&gt;
			// Fallback&lt;br /&gt;
			indication_icon: &#039;//upload.wikimedia.org/wikipedia/commons/8/8a/Gtk-dialog-info-14px.png&#039;,&lt;br /&gt;
&lt;br /&gt;
			install: function ( config ) {&lt;br /&gt;
				if ( typeof ImageAnnotator_disable !== &#039;undefined&#039; &amp;amp;&amp;amp; !!ImageAnnotator_disable ) { return; }&lt;br /&gt;
				if ( !config || ImageAnnotator_config != null ) { return; }&lt;br /&gt;
&lt;br /&gt;
				// Double check.&lt;br /&gt;
				if ( !config.viewingEnabled() ) { return; }&lt;br /&gt;
&lt;br /&gt;
				var self = IA;&lt;br /&gt;
				ImageAnnotator_config = config;&lt;br /&gt;
&lt;br /&gt;
				// Determine whether we have XmlHttp. We try to determine this here to be able to avoid&lt;br /&gt;
				// doing too much work.&lt;br /&gt;
				if (&lt;br /&gt;
					window.XMLHttpRequest &amp;amp;&amp;amp;&lt;br /&gt;
					typeof LAPI !== &#039;undefined&#039; &amp;amp;&amp;amp;&lt;br /&gt;
					typeof LAPI.Ajax !== &#039;undefined&#039; &amp;amp;&amp;amp;&lt;br /&gt;
					typeof LAPI.Ajax.getRequest !== &#039;undefined&#039;&lt;br /&gt;
				) {&lt;br /&gt;
					self.haveAjax = ( LAPI.Ajax.getRequest() != null );&lt;br /&gt;
					self.ajaxQueried = true;&lt;br /&gt;
				} else {&lt;br /&gt;
					self.haveAjax = true; // A pity. May occur on IE. We&#039;ll check again later on.&lt;br /&gt;
					self.ajaxQueried = false;&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				// We&#039;ll include self.haveAjax later on once more, to catch the !ajaxQueried case.&lt;br /&gt;
				self.may_edit = mw.config.get( &#039;wgNamespaceNumber&#039; ) &amp;gt;= 0 &amp;amp;&amp;amp; mw.config.get( &#039;wgArticleId&#039; ) &amp;gt; 0 &amp;amp;&amp;amp; self.haveAjax &amp;amp;&amp;amp; config.editingEnabled();&lt;br /&gt;
&lt;br /&gt;
				function namespaceCheck( list ) {&lt;br /&gt;
					if ( !list || Object.prototype.toString.call( list ) !== &#039;[object Array]&#039; ) { return false; }&lt;br /&gt;
					var namespaceIds = mw.config.get( &#039;wgNamespaceIds&#039; );&lt;br /&gt;
					if ( !namespaceIds ) { return false; }&lt;br /&gt;
					var namespaceNumber = mw.config.get( &#039;wgNamespaceNumber&#039; );&lt;br /&gt;
					for ( var i = 0; i &amp;lt; list.length; i++ ) {&lt;br /&gt;
						if (&lt;br /&gt;
							typeof list[ i ] === &#039;string&#039; &amp;amp;&amp;amp;&lt;br /&gt;
							(&lt;br /&gt;
								list[ i ] === &#039;*&#039; ||&lt;br /&gt;
								namespaceIds[ list[ i ].toLowerCase().replace( / /g, &#039;_&#039; ) ] === namespaceNumber&lt;br /&gt;
							)&lt;br /&gt;
						) {&lt;br /&gt;
							return true;&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
					return false;&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				self.rules = { inline: {}, thumbs: {}, shared: {} };&lt;br /&gt;
&lt;br /&gt;
				// Now set the default rules. Undefined means default setting (true for show, false for icon),&lt;br /&gt;
				// but overrideable by per-image rules. If set, it&#039;s not overrideable by per-image rules.&lt;br /&gt;
				//&lt;br /&gt;
				if (&lt;br /&gt;
					!self.haveAjax ||&lt;br /&gt;
					!config.generalImagesEnabled() ||&lt;br /&gt;
					namespaceCheck( window.ImageAnnotator_no_images || null )&lt;br /&gt;
				) {&lt;br /&gt;
					self.rules.inline.show = false;&lt;br /&gt;
					self.rules.thumbs.show = false;&lt;br /&gt;
					self.rules.shared.show = false;&lt;br /&gt;
				} else {&lt;br /&gt;
					if (&lt;br /&gt;
						!self.haveAjax ||&lt;br /&gt;
						!config.thumbsEnabled() ||&lt;br /&gt;
						namespaceCheck( window.ImageAnnotator_no_thumbs || null )&lt;br /&gt;
					) {&lt;br /&gt;
						self.rules.thumbs.show = false;&lt;br /&gt;
					}&lt;br /&gt;
					if ( mw.config.get( &#039;wgNamespaceNumber&#039; ) == 6 ) {&lt;br /&gt;
						self.rules.shared.show = true;&lt;br /&gt;
					} else if ( !config.sharedImagesEnabled() ||&lt;br /&gt;
						namespaceCheck( window.ImageAnnotator_no_shared || null )&lt;br /&gt;
					) {&lt;br /&gt;
						self.rules.shared.show = false;&lt;br /&gt;
					}&lt;br /&gt;
					if ( namespaceCheck( window.ImageAnnotator_icon_images || null ) ) { self.rules.inline.icon = true; }&lt;br /&gt;
					if ( namespaceCheck( window.ImageAnnotator_icon_thumbs || null ) ) { self.rules.thumbs.icon = true; }&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				// User rule for displaying captions on images in articles&lt;br /&gt;
				self.hideCaptions = namespaceCheck( window.ImageAnnotator_hide_captions || null );&lt;br /&gt;
&lt;br /&gt;
				var do_images = typeof self.rules.inline.show === &#039;undefined&#039; || self.rules.inline.show;&lt;br /&gt;
&lt;br /&gt;
				if ( do_images ) {&lt;br /&gt;
					// Per-article switching off of note display on inline images and thumbnails&lt;br /&gt;
					var rules = document.getElementById( &#039;wpImageAnnotatorImageRules&#039; );&lt;br /&gt;
					if ( rules ) {&lt;br /&gt;
						if ( rules.className.indexOf( &#039;wpImageAnnotatorNone&#039; ) &amp;gt;= 0 ) {&lt;br /&gt;
							self.rules.inline.show = false;&lt;br /&gt;
							self.rules.thumbs.show = false;&lt;br /&gt;
							self.rules.shared.show = false;&lt;br /&gt;
						}&lt;br /&gt;
						if (&lt;br /&gt;
							typeof self.rules.inline.show === &#039;undefined&#039; &amp;amp;&amp;amp;&lt;br /&gt;
							rules.className.indexOf( &#039;wpImageAnnotatorDisplay&#039; ) &amp;gt;= 0&lt;br /&gt;
						) {&lt;br /&gt;
							self.rules.inline.show = true;&lt;br /&gt;
						}&lt;br /&gt;
						if ( rules.className.indexOf( &#039;wpImageAnnotatorNoThumbDisplay&#039; ) &amp;gt;= 0 ) {&lt;br /&gt;
							self.rules.thumbs.show = false;&lt;br /&gt;
						}&lt;br /&gt;
						if (&lt;br /&gt;
							typeof self.rules.thumbs.show === &#039;undefined&#039; &amp;amp;&amp;amp;&lt;br /&gt;
							rules.className.indexOf( &#039;wpImageAnnotatorThumbDisplay&#039; ) &amp;gt;= 0&lt;br /&gt;
						) {&lt;br /&gt;
							self.rules.thumbs.show = true;&lt;br /&gt;
						}&lt;br /&gt;
						if ( rules.className.indexOf( &#039;wpImageAnnotatorInlineDisplayIcons&#039; ) &amp;gt;= 0 ) {&lt;br /&gt;
							self.rules.inline.icon = true;&lt;br /&gt;
						}&lt;br /&gt;
						if ( rules.className.indexOf( &#039;wpImageAnnotatorThumbDisplayIcons&#039; ) &amp;gt;= 0 ) {&lt;br /&gt;
							self.rules.thumbs.icon = true;&lt;br /&gt;
						}&lt;br /&gt;
						if ( rules.className.indexOf( &#039;wpImageAnnotatorOnlyLocal&#039; ) &amp;gt;= 0 ) {&lt;br /&gt;
							self.rules.shared.show = false;&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				// Make sure the shared value is set&lt;br /&gt;
				self.rules.shared.show = typeof self.rules.shared.show === &#039;undefined&#039; || self.rules.shared.show;&lt;br /&gt;
&lt;br /&gt;
				var do_thumbs = typeof self.rules.thumbs.show === &#039;undefined&#039; || self.rules.thumbs.show;&lt;br /&gt;
&lt;br /&gt;
				if ( do_images ) {&lt;br /&gt;
					var bodyContent = document.getElementById( &#039;bodyContent&#039; ) || // monobook, vector&lt;br /&gt;
						document.getElementById( &#039;mw_contentholder&#039; ) || // modern&lt;br /&gt;
						document.getElementById( &#039;article&#039; ); // old skins&lt;br /&gt;
&lt;br /&gt;
					if ( bodyContent ) {&lt;br /&gt;
						var all_imgs = bodyContent.getElementsByTagName( &#039;img&#039; );&lt;br /&gt;
&lt;br /&gt;
						// This prevents traversing a page with more than 400 images&lt;br /&gt;
						// There are extreme cases like [[Emoji]] that high number of images can cause&lt;br /&gt;
						// huge lag specially on Chrome&lt;br /&gt;
						if ( all_imgs.length &amp;gt; 400 ) {&lt;br /&gt;
							// purging the array, simply a hack to avoid more indention&lt;br /&gt;
							all_imgs = [];&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
						for ( var i = 0; i &amp;lt; all_imgs.length; i++ ) {&lt;br /&gt;
							// Exclude all that are in img_with_notes or in thumbs. Also exclude all in galleries.&lt;br /&gt;
							var up = all_imgs[ i ].parentNode;&lt;br /&gt;
							if ( up.nodeName.toLowerCase() !== &#039;a&#039; ) { continue; }&lt;br /&gt;
							up = up.parentNode;&lt;br /&gt;
							if ( ( &#039; &#039; + up.className + &#039; &#039; ).indexOf( &#039; wpImageAnnotatorOff &#039; ) &amp;gt;= 0 ) { continue; }&lt;br /&gt;
							if ( ( &#039; &#039; + up.className + &#039; &#039; ).indexOf( &#039; thumbinner &#039; ) &amp;gt;= 0 ) {&lt;br /&gt;
								if ( do_thumbs ) { self.thumbs[ self.thumbs.length ] = up; }&lt;br /&gt;
								continue;&lt;br /&gt;
							}&lt;br /&gt;
							up = up.parentNode;&lt;br /&gt;
							if ( !up ) { continue; }&lt;br /&gt;
							if ( ( &#039; &#039; + up.className + &#039; &#039; ).indexOf( &#039; wpImageAnnotatorOff &#039; ) &amp;gt;= 0 ) { continue; }&lt;br /&gt;
							if ( ( &#039; &#039; + up.className + &#039; &#039; ).indexOf( &#039; wpImageAnnotatorEnable &#039; ) &amp;gt;= 0 ) {&lt;br /&gt;
								self.imgs_with_notes[ self.imgs_with_notes.length ] = up;&lt;br /&gt;
								continue;&lt;br /&gt;
							}&lt;br /&gt;
							up = up.parentNode;&lt;br /&gt;
							if ( !up ) { continue; }&lt;br /&gt;
							// Other images not in galleries&lt;br /&gt;
							if ( ( &#039; &#039; + up.className + &#039; &#039; ).indexOf( &#039; wpImageAnnotatorOff &#039; ) &amp;gt;= 0 ) { continue; }&lt;br /&gt;
							if ( ( &#039; &#039; + up.className + &#039; &#039; ).indexOf( &#039; gallerybox &#039; ) &amp;gt;= 0 ) { continue; }&lt;br /&gt;
							if ( ( &#039; &#039; + up.className + &#039; &#039; ).indexOf( &#039; wpImageAnnotatorEnable &#039; ) &amp;gt;= 0 ) {&lt;br /&gt;
								self.imgs_with_notes[ self.imgs_with_notes.length ] = up;&lt;br /&gt;
								continue;&lt;br /&gt;
							}&lt;br /&gt;
							up = up.parentNode;&lt;br /&gt;
							if ( !up ) { continue; }&lt;br /&gt;
							if ( ( &#039; &#039; + up.className + &#039; &#039; ).indexOf( &#039; wpImageAnnotatorOff &#039; ) &amp;gt;= 0 ) { continue; }&lt;br /&gt;
							if ( ( &#039; &#039; + up.className + &#039; &#039; ).indexOf( &#039; gallerybox &#039; ) &amp;gt;= 0 ) { continue; }&lt;br /&gt;
							if ( ( &#039; &#039; + up.className + &#039; &#039; ).indexOf( &#039; wpImageAnnotatorEnable &#039; ) &amp;gt;= 0 ) {&lt;br /&gt;
								self.imgs_with_notes[ self.imgs_with_notes.length ] = up;&lt;br /&gt;
							} else {&lt;br /&gt;
								// Guard against other scripts adding aribtrary numbers of divs (dshuf for instance!)&lt;br /&gt;
								var is_other = true;&lt;br /&gt;
								while ( up &amp;amp;&amp;amp; up.nodeName.toLowerCase() == &#039;div&#039; &amp;amp;&amp;amp; is_other ) {&lt;br /&gt;
									up = up.parentNode;&lt;br /&gt;
									if ( up ) { is_other = ( &#039; &#039; + up.className + &#039; &#039; ).indexOf( &#039; gallerybox &#039; ) &amp;lt; 0; }&lt;br /&gt;
								}&lt;br /&gt;
								if ( is_other ) { self.other_images[ self.other_images.length ] = all_imgs[ i ]; }&lt;br /&gt;
							}&lt;br /&gt;
						} // end loop&lt;br /&gt;
					}&lt;br /&gt;
				} else {&lt;br /&gt;
					self.imgs_with_notes = getElementsByClassName( document, &#039;*&#039;, &#039;wpImageAnnotatorEnable&#039; );&lt;br /&gt;
					if ( do_thumbs ) { self.thumbs = getElementsByClassName( document, &#039;div&#039;, &#039;thumbinner&#039; ); } // No galleries!&lt;br /&gt;
				}&lt;br /&gt;
				if (&lt;br /&gt;
					mw.config.get( &#039;wgNamespaceNumber&#039; ) == 6 ||&lt;br /&gt;
					( self.imgs_with_notes.length ) ||&lt;br /&gt;
					( self.thumbs.length ) ||&lt;br /&gt;
					( self.other_images.length )&lt;br /&gt;
				) {&lt;br /&gt;
					// Publish parts of config.&lt;br /&gt;
					ImageAnnotator.UI = config.UI;&lt;br /&gt;
					self.outer_border = config.outer_border;&lt;br /&gt;
					self.inner_border = config.inner_border;&lt;br /&gt;
					self.active_border = config.active_border;&lt;br /&gt;
					self.new_border = config.new_border;&lt;br /&gt;
					self.wait_for_required_libraries();&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			wait_for_required_libraries: function () {&lt;br /&gt;
				if ( typeof Tooltip === &#039;undefined&#039; || typeof LAPI === &#039;undefined&#039; ) {&lt;br /&gt;
					if ( IA.install_attempts++ &amp;lt; IA.max_install_attempts ) {&lt;br /&gt;
						setTimeout( IA.wait_for_required_libraries, 500 ); // 0.5 sec.&lt;br /&gt;
					}&lt;br /&gt;
					return;&lt;br /&gt;
				}&lt;br /&gt;
				if ( LAPI.Browser.is_opera &amp;amp;&amp;amp; !LAPI.Browser.is_opera_ge_9 ) { return; } // Opera 8 has severe problems&lt;br /&gt;
				// Get the UI. We&#039;re likely to need it if we made it to here.&lt;br /&gt;
				IA.setup_ui();&lt;br /&gt;
				IA.setup();&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			setup: function () {&lt;br /&gt;
				var self = IA;&lt;br /&gt;
				self.imgs = [];&lt;br /&gt;
&lt;br /&gt;
				// Catch both native RTL and &amp;quot;faked&amp;quot; RTL through [[MediaWiki:Rtl.js]]&lt;br /&gt;
				self.is_rtl =&lt;br /&gt;
					LAPI.DOM.hasClass( document.body, &#039;rtl&#039; ) ||&lt;br /&gt;
					(&lt;br /&gt;
						LAPI.DOM.currentStyle &amp;amp;&amp;amp; // Paranoia: added recently, not everyone might have it&lt;br /&gt;
						LAPI.DOM.currentStyle( document.body, &#039;direction&#039; ) == &#039;rtl&#039;&lt;br /&gt;
					);&lt;br /&gt;
&lt;br /&gt;
				var stylepath = mw.config.get( &#039;stylepath&#039; ) || &#039;/skin&#039;;&lt;br /&gt;
&lt;br /&gt;
				// Use this to temporarily display an image off-screen to get its dimensions&lt;br /&gt;
				var testImgDiv = LAPI.make(&lt;br /&gt;
					&#039;div&#039;, null,&lt;br /&gt;
					{&lt;br /&gt;
						display: &#039;none&#039;, position: &#039;absolute&#039;, width: &#039;300px&#039;,&lt;br /&gt;
						overflow: &#039;hidden&#039;, overflowX: &#039;hidden&#039;, left: &#039;-10000px&#039;&lt;br /&gt;
					}&lt;br /&gt;
				);&lt;br /&gt;
				document.body.insertBefore( testImgDiv, document.body.firstChild );&lt;br /&gt;
&lt;br /&gt;
				function img_check( img, is_other ) {&lt;br /&gt;
					var srcW = parseInt( img.getAttribute( &#039;width&#039;, 2 ), 10 );&lt;br /&gt;
					var srcH = parseInt( img.getAttribute( &#039;height&#039;, 2 ), 10 );&lt;br /&gt;
					// Don&#039;t do anything on extremely small previews. We need some minimum extent to be able to place&lt;br /&gt;
					// rectangles after all...&lt;br /&gt;
					if ( !srcW || !srcH || srcW &amp;lt; 20 || srcH &amp;lt; 20 ) { return null; }&lt;br /&gt;
					// For non-thumbnail images, the size limit is larger.&lt;br /&gt;
					if ( is_other &amp;amp;&amp;amp; ( srcW &amp;lt; 60 || srcH &amp;lt; 60 ) ) { return null; }&lt;br /&gt;
					var w = img.clientWidth; // Don&#039;t use offsetWidth, thumbnails may have a boundary...&lt;br /&gt;
					var h = img.clientHeight;&lt;br /&gt;
					// If the image is currently hidden, its clientWidth and clientHeight are not set. Try&lt;br /&gt;
					// harder to get the true width and height:&lt;br /&gt;
					if ( ( !w || !h ) &amp;amp;&amp;amp; img.style.display != &#039;none&#039; ) {&lt;br /&gt;
						var copied = img.cloneNode( true );&lt;br /&gt;
						copied.style.display = &#039;&#039;;&lt;br /&gt;
						testImgDiv.appendChild( copied );&lt;br /&gt;
						testImgDiv.style.display = &#039;&#039;;&lt;br /&gt;
						w = copied.clientWidth;&lt;br /&gt;
						h = copied.clientHeight;&lt;br /&gt;
						testImgDiv.style.display = &#039;none&#039;;&lt;br /&gt;
						LAPI.DOM.removeNode( copied );&lt;br /&gt;
					}&lt;br /&gt;
					// Quit if the image wasn&#039;t loaded properly for some reason:&lt;br /&gt;
					if ( w != srcW || h != srcH ) { return null; }&lt;br /&gt;
					// Exclude system images&lt;br /&gt;
					if ( img.src.contains( stylepath ) ) { return null; }&lt;br /&gt;
					// Only if within a link&lt;br /&gt;
					if ( img.parentNode.nodeName.toLowerCase() != &#039;a&#039; ) { return null; }&lt;br /&gt;
					if ( is_other ) {&lt;br /&gt;
						// Only if the img-within-link construction is within some element that may contain a div!&lt;br /&gt;
						if ( /^(p|span)$/i.test( img.parentNode.parentNode.nodeName ) ) {&lt;br /&gt;
							// Special case: a paragraph may contain only inline elements, but we want to be able to handle&lt;br /&gt;
							// files in single paragraphs. Maybe we need to properly split the paragraph and wrap the image&lt;br /&gt;
							// in a div, but for now we assume that all browsers can handle a div within a paragraph or&lt;br /&gt;
							// a span in a meaningful way, even if that is not really allowed.&lt;br /&gt;
						} else if ( !/^(object|applet|map|fieldset|noscript|iframe|body|div|li|dd|blockquote|center|ins|del|button|th|td|form)$/i.test( img.parentNode.parentNode.nodeName ) ) { return null; }&lt;br /&gt;
					}&lt;br /&gt;
					// Exclude any that are within an image note!&lt;br /&gt;
					var up = img.parentNode.parentNode;&lt;br /&gt;
					while ( up != document.body ) {&lt;br /&gt;
						if ( LAPI.DOM.hasClass( up, IA.annotation_class ) ) { return null; }&lt;br /&gt;
						up = up.parentNode;&lt;br /&gt;
					}&lt;br /&gt;
					return { width: w, height: h };&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				function setup_one( scope ) {&lt;br /&gt;
					var file_div = scope;&lt;br /&gt;
					var is_thumb =&lt;br /&gt;
						scope != document &amp;amp;&amp;amp;&lt;br /&gt;
						scope.nodeName.toLowerCase() == &#039;div&#039; &amp;amp;&amp;amp;&lt;br /&gt;
						LAPI.DOM.hasClass( scope, &#039;thumbinner&#039; );&lt;br /&gt;
					var is_other = scope.nodeName.toLowerCase() == &#039;img&#039;;&lt;br /&gt;
					if ( is_other &amp;amp;&amp;amp; self.imgs.length &amp;amp;&amp;amp; scope == self.imgs[ 0 ] ) { return null; }&lt;br /&gt;
					if ( scope == document ) {&lt;br /&gt;
						file_div = LAPI.$( &#039;file&#039; );&lt;br /&gt;
					} else if ( !is_thumb &amp;amp;&amp;amp; !is_other ) {&lt;br /&gt;
						file_div = getElementsByClassName( scope, &#039;div&#039;, &#039;wpImageAnnotatorFile&#039; );&lt;br /&gt;
						if ( !file_div || file_div.length != 1 ) { return null; }&lt;br /&gt;
						file_div = file_div[ 0 ];&lt;br /&gt;
					}&lt;br /&gt;
					if ( !file_div ) { return null; }&lt;br /&gt;
					var img = null;&lt;br /&gt;
					if ( scope == document ) {&lt;br /&gt;
						img = LAPI.WP.getPreviewImage( mw.config.get( &#039;wgTitle&#039; ) );&lt;br /&gt;
						// TIFFs may be multi-paged: allow only for single-page TIFFs&lt;br /&gt;
						if ( document.pageselector ) { img = null; }&lt;br /&gt;
					} else if ( is_other ) {&lt;br /&gt;
						img = scope;&lt;br /&gt;
					} else {&lt;br /&gt;
						img = file_div.getElementsByTagName( &#039;img&#039; );&lt;br /&gt;
						if ( !img || img.length === 0 ) { return null; }&lt;br /&gt;
						img = img[ 0 ];&lt;br /&gt;
					}&lt;br /&gt;
					if ( !img ) { return null; }&lt;br /&gt;
					var dim = img_check( img, is_other );&lt;br /&gt;
					if ( !dim ) { return null; }&lt;br /&gt;
					// Conditionally exclude shared images.&lt;br /&gt;
					if (&lt;br /&gt;
						scope != document &amp;amp;&amp;amp;&lt;br /&gt;
						!self.rules.shared.show &amp;amp;&amp;amp;&lt;br /&gt;
						ImageAnnotator_config.imageIsFromSharedRepository( img.src )&lt;br /&gt;
					) { return null; }&lt;br /&gt;
					var name = null;&lt;br /&gt;
					if ( scope == document ) {&lt;br /&gt;
						name = mw.config.get( &#039;wgPageName&#039; );&lt;br /&gt;
					} else {&lt;br /&gt;
						name = LAPI.WP.pageFromLink( img.parentNode );&lt;br /&gt;
						if ( !name ) { return null; }&lt;br /&gt;
						name = name.replace( / /g, &#039;_&#039; );&lt;br /&gt;
						if ( is_thumb || is_other ) {&lt;br /&gt;
							var img_src = decodeURIComponent( img.getAttribute( &#039;src&#039;, 2 ) ).replace( / /g, &#039;_&#039; );&lt;br /&gt;
							// img_src should have a component &amp;quot;/name&amp;quot; in there somewhere&lt;br /&gt;
							var colon = name.indexOf( &#039;:&#039; );&lt;br /&gt;
							if ( colon &amp;lt;= 0 ) { return null; }&lt;br /&gt;
							var img_name = name.substring( colon + 1 );&lt;br /&gt;
							if ( img_src.search( new RegExp( &#039;/&#039; + img_name.escapeRE() + &#039;(/.*)?$&#039; ) ) &amp;lt; 0 ) { return null; }&lt;br /&gt;
							// If the link is not going to file namespace, we won&#039;t find the full size later on and&lt;br /&gt;
							// thus we won&#039;t do anything with it.&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
					if ( name.search( /\.(jpe?g|png|gif|svg|tiff?|webp)$/i ) &amp;lt; 0 ) { return null; } // Only PNG, JPE?G, GIF, SVG, TIFF?, and WebP&lt;br /&gt;
					// Finally check for wpImageAnnotatorControl&lt;br /&gt;
					var icon_only = false;&lt;br /&gt;
					var no_caption = false;&lt;br /&gt;
					if ( is_thumb || is_other ) {&lt;br /&gt;
						var up = img.parentNode.parentNode;&lt;br /&gt;
						// Three levels is sufficient: thumbinner-thumb-control, or floatnone-center-control, or direct&lt;br /&gt;
						for ( var i = 0; ++i &amp;lt;= 3 &amp;amp;&amp;amp; up; up = up.parentNode ) {&lt;br /&gt;
							if ( LAPI.DOM.hasClass( up, &#039;wpImageAnnotatorControl&#039; ) ) {&lt;br /&gt;
								if ( LAPI.DOM.hasClass( up, &#039;wpImageAnnotatorOff&#039; ) ) { return null; }&lt;br /&gt;
								if ( LAPI.DOM.hasClass( up, &#039;wpImageAnnotatorIconOnly&#039; ) ) { icon_only = true; }&lt;br /&gt;
								if ( LAPI.DOM.hasClass( up, &#039;wpImageAnnotatorCaptionOff&#039; ) ) { no_caption = true; }&lt;br /&gt;
								break;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
					return { scope: scope,&lt;br /&gt;
						file_div: file_div,&lt;br /&gt;
						img: img,&lt;br /&gt;
						realName: name,&lt;br /&gt;
						isThumbnail: is_thumb,&lt;br /&gt;
						isOther: is_other,&lt;br /&gt;
						thumb: { width: dim.width, height: dim.height },&lt;br /&gt;
						iconOnly: icon_only,&lt;br /&gt;
						noCaption: no_caption&lt;br /&gt;
					};&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				function setup_images( list ) {&lt;br /&gt;
					Array.forEach( list,&lt;br /&gt;
						function ( elem ) {&lt;br /&gt;
							var desc = setup_one( elem );&lt;br /&gt;
							if ( desc ) { self.imgs[ self.imgs.length ] = desc; }&lt;br /&gt;
						}&lt;br /&gt;
					);&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				if ( mw.config.get( &#039;wgNamespaceNumber&#039; ) == 6 ) {&lt;br /&gt;
					setup_images( [ document ] );&lt;br /&gt;
					self.may_edit = self.may_edit &amp;amp;&amp;amp; ( self.imgs.length == 1 );&lt;br /&gt;
					setup_images( self.imgs_with_notes );&lt;br /&gt;
				} else {&lt;br /&gt;
					setup_images( self.imgs_with_notes );&lt;br /&gt;
					self.may_edit = self.may_edit &amp;amp;&amp;amp; ( self.imgs.length == 1 );&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				self.may_edit = self.may_edit &amp;amp;&amp;amp; location.href.search( /[?&amp;amp;]oldid=/ ) &amp;lt; 0;&lt;br /&gt;
&lt;br /&gt;
				if ( self.haveAjax ) {&lt;br /&gt;
					setup_images( self.thumbs );&lt;br /&gt;
					setup_images( self.other_images );&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				// Remove the test div&lt;br /&gt;
				LAPI.DOM.removeNode( testImgDiv );&lt;br /&gt;
&lt;br /&gt;
				if ( self.imgs.length === 0 ) { return; }&lt;br /&gt;
&lt;br /&gt;
				// We get the UI texts in parallel, but wait for them at the beginning of complete_setup, where we&lt;br /&gt;
				// need them. This has in particular a benefit if we do have to query for the file sizes below.&lt;br /&gt;
&lt;br /&gt;
				if ( self.imgs.length == 1 &amp;amp;&amp;amp; self.imgs[ 0 ].scope == document &amp;amp;&amp;amp; !self.haveAjax ) {&lt;br /&gt;
					// Try to get the full size without Ajax.&lt;br /&gt;
					self.imgs[ 0 ].full_img = LAPI.WP.fullImageSizeFromPage();&lt;br /&gt;
					if ( self.imgs[ 0 ].full_img.width &amp;gt; 0 &amp;amp;&amp;amp; self.imgs[ 0 ].full_img.height &amp;gt; 0 ) {&lt;br /&gt;
						self.setup_step_two();&lt;br /&gt;
						return;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				// Get the full sizes of all the images. If more than 50, make several calls. (The API has limits.)&lt;br /&gt;
				// Also avoid using Ajax on IE6...&lt;br /&gt;
&lt;br /&gt;
				var cache = {};&lt;br /&gt;
				var names = [];&lt;br /&gt;
&lt;br /&gt;
				Array.forEach( self.imgs, function ( img, idx ) {&lt;br /&gt;
					if ( cache[ img.realName ] ) {&lt;br /&gt;
						cache[ img.realName ][ cache[ img.realName ].length ] = idx;&lt;br /&gt;
					} else {&lt;br /&gt;
						cache[ img.realName ] = [ idx ];&lt;br /&gt;
						names[ names.length ] = img.realName;&lt;br /&gt;
					}&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				var to_do = names.length;&lt;br /&gt;
				var done = 0;&lt;br /&gt;
&lt;br /&gt;
				function check_done( length ) {&lt;br /&gt;
					done += length;&lt;br /&gt;
					if ( done &amp;gt;= names.length ) {&lt;br /&gt;
						if ( typeof ImageAnnotator.info_callbacks !== &#039;undefined&#039; ) { ImageAnnotator.info_callbacks = null; }&lt;br /&gt;
						self.setup_step_two();&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				function make_calls( execute_call, url_limit ) {&lt;br /&gt;
					function build_titles( from, length, url_limit ) {&lt;br /&gt;
						var done = 0;&lt;br /&gt;
						var text = &#039;&#039;;&lt;br /&gt;
						for ( var i = from; i &amp;lt; from + length; i++ ) {&lt;br /&gt;
							var new_text = names[ i ];&lt;br /&gt;
							if ( url_limit ) {&lt;br /&gt;
								new_text = encodeURIComponent( new_text );&lt;br /&gt;
								if ( text.length &amp;amp;&amp;amp; ( text.length + new_text.length + 1 &amp;gt; url_limit ) ) { break; }&lt;br /&gt;
							}&lt;br /&gt;
							text += ( text.length ? &#039;|&#039; : &#039;&#039; ) + new_text;&lt;br /&gt;
							done++;&lt;br /&gt;
						}&lt;br /&gt;
						return { text: text, n: done };&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					var start = 0, chunk = 0, params;&lt;br /&gt;
					while ( to_do &amp;gt; 0 ) {&lt;br /&gt;
						params = build_titles( start, Math.min( 50, to_do ), url_limit );&lt;br /&gt;
						execute_call( params.n, params.text );&lt;br /&gt;
						to_do -= params.n;&lt;br /&gt;
						start += params.n;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				function set_info( json ) {&lt;br /&gt;
					try {&lt;br /&gt;
						if ( json &amp;amp;&amp;amp; json.query &amp;amp;&amp;amp; json.query.pages ) {&lt;br /&gt;
							function get_size( info ) {&lt;br /&gt;
								if ( !info.imageinfo || info.imageinfo.length === 0 ) { return; }&lt;br /&gt;
								var title = info.title.replace( / /g, &#039;_&#039; );&lt;br /&gt;
								var indices = cache[ title ];&lt;br /&gt;
								if ( !indices ) { return; }&lt;br /&gt;
								Array.forEach(&lt;br /&gt;
									indices&lt;br /&gt;
									, function ( i ) {&lt;br /&gt;
										self.imgs[ i ].full_img = { width: info.imageinfo[ 0 ].width,&lt;br /&gt;
											height: info.imageinfo[ 0 ].height };&lt;br /&gt;
										self.imgs[ i ].has_page = ( typeof info.missing === &#039;undefined&#039; );&lt;br /&gt;
										self.imgs[ i ].isLocal = !info.imagerepository || info.imagerepository == &#039;local&#039;;&lt;br /&gt;
										if ( i != 0 || !self.may_edit || !info.protection || mw.config.get( &#039;wgNamespaceNumber&#039; ) != 6 ) { return; }&lt;br /&gt;
										// Care about the protection settings&lt;br /&gt;
										var protection = Array.any( info.protection, function ( e ) {&lt;br /&gt;
											return ( e.type == &#039;edit&#039; ? e : null );&lt;br /&gt;
										} );&lt;br /&gt;
										self.may_edit =&lt;br /&gt;
											!protection ||&lt;br /&gt;
											( mw.config.get( &#039;wgUserGroups&#039; ) &amp;amp;&amp;amp; mw.config.get( &#039;wgUserGroups&#039; ).join( &#039; &#039; ).contains( protection.level ) );&lt;br /&gt;
									}&lt;br /&gt;
								);&lt;br /&gt;
							}&lt;br /&gt;
							for ( var page in json.query.pages ) {&lt;br /&gt;
								get_size( json.query.pages[ page ] );&lt;br /&gt;
							}&lt;br /&gt;
						} // end if&lt;br /&gt;
					} catch ( ex ) {&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				if ( ( !window.XMLHttpRequest &amp;amp;&amp;amp; !!window.ActiveXObject ) || !self.haveAjax ) {&lt;br /&gt;
					// IE has a stupid security setting asking whether ActiveX should be allowed. We avoid that&lt;br /&gt;
					// prompt by using getScript instead of parseWikitext in this case.&lt;br /&gt;
					ImageAnnotator.info_callbacks = [];&lt;br /&gt;
					var template = mw.config.get( &#039;wgServer&#039; ) + mw.config.get( &#039;wgScriptPath&#039; ) + &#039;/api.php?action=query&amp;amp;format=json&#039; +&lt;br /&gt;
						&#039;&amp;amp;prop=info|imageinfo&amp;amp;inprop=protection&amp;amp;iiprop=size&#039; +&lt;br /&gt;
						&#039;&amp;amp;titles=&amp;amp;callback=ImageAnnotator.info_callbacks[].callback&#039;;&lt;br /&gt;
					if ( template.startsWith( &#039;//&#039; ) ) { template = document.location.protocol + template; } // Avoid protocol-relative URIs (IE7 bug)&lt;br /&gt;
					make_calls(&lt;br /&gt;
						function ( length, titles ) {&lt;br /&gt;
							var idx = ImageAnnotator.info_callbacks.length;&lt;br /&gt;
							ImageAnnotator.info_callbacks[ idx ] = {&lt;br /&gt;
								callback: function ( json ) {&lt;br /&gt;
									set_info( json );&lt;br /&gt;
									ImageAnnotator.info_callbacks[ idx ].done = true;&lt;br /&gt;
									if ( ImageAnnotator.info_callbacks[ idx ].script ) {&lt;br /&gt;
										LAPI.DOM.removeNode( ImageAnnotator.info_callbacks[ idx ].script );&lt;br /&gt;
										ImageAnnotator.info_callbacks[ idx ].script = null;&lt;br /&gt;
									}&lt;br /&gt;
									check_done( length );&lt;br /&gt;
								},&lt;br /&gt;
								done: false&lt;br /&gt;
							};&lt;br /&gt;
							ImageAnnotator.info_callbacks[ idx ].script = IA.getScript(&lt;br /&gt;
								template.replace( &#039;info_callbacks[].callback&#039;, &#039;info_callbacks[&#039; + idx + &#039;].callback&#039; )&lt;br /&gt;
									.replace( &#039;&amp;amp;titles=&amp;amp;&#039;, &#039;&amp;amp;titles=&#039; + titles + &#039;&amp;amp;&#039; ),&lt;br /&gt;
								true // No local caching!&lt;br /&gt;
							);&lt;br /&gt;
							// We do bypass the local JavaScript cache of importScriptURI, but on IE, we still may&lt;br /&gt;
							// get the script from the browser&#039;s cache, and if that happens, IE may execute the&lt;br /&gt;
							// script (and call the callback) synchronously before the assignment is done. Clean&lt;br /&gt;
							// up in that case.&lt;br /&gt;
							if (&lt;br /&gt;
								ImageAnnotator.info_callbacks &amp;amp;&amp;amp; ImageAnnotator.info_callbacks[ idx ] &amp;amp;&amp;amp;&lt;br /&gt;
								ImageAnnotator.info_callbacks[ idx ].done &amp;amp;&amp;amp; ImageAnnotator.info_callbacks[ idx ].script&lt;br /&gt;
							) {&lt;br /&gt;
								LAPI.DOM.removeNode( ImageAnnotator.info_callbacks[ idx ].script );&lt;br /&gt;
								ImageAnnotator.info_callbacks[ idx ].script = null;&lt;br /&gt;
							}&lt;br /&gt;
						},&lt;br /&gt;
						( LAPI.Browser.is_ie ? 1950 : 4000 ) - template.length // Some slack for caching parameters&lt;br /&gt;
					);&lt;br /&gt;
				} else {&lt;br /&gt;
					make_calls(&lt;br /&gt;
						function ( length, titles ) {&lt;br /&gt;
							LAPI.Ajax.apiGet(&lt;br /&gt;
								&#039;query&#039;&lt;br /&gt;
								, { titles: titles,&lt;br /&gt;
									prop: &#039;info|imageinfo&#039;,&lt;br /&gt;
									inprop: &#039;protection&#039;,&lt;br /&gt;
									iiprop: &#039;size&#039;&lt;br /&gt;
								}&lt;br /&gt;
								, function ( request, json_result ) {&lt;br /&gt;
									set_info( json_result );&lt;br /&gt;
									check_done( length );&lt;br /&gt;
								}&lt;br /&gt;
								, function () { check_done( length ); }&lt;br /&gt;
							);&lt;br /&gt;
						}&lt;br /&gt;
					);&lt;br /&gt;
				} // end if can use Ajax&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			setup_ui: function () {&lt;br /&gt;
				// Complete the UI object we&#039;ve gotten from config.&lt;br /&gt;
&lt;br /&gt;
				ImageAnnotator.UI.ready = false;&lt;br /&gt;
				ImageAnnotator.UI.repo = null;&lt;br /&gt;
				ImageAnnotator.UI.needs_plea = false;&lt;br /&gt;
&lt;br /&gt;
				var readyEvent = [];&lt;br /&gt;
&lt;br /&gt;
				ImageAnnotator.UI.fireReadyEvent = function () {&lt;br /&gt;
					if ( ImageAnnotator.UI.ready ) { return; } // Already fired, nothing to do.&lt;br /&gt;
					ImageAnnotator.UI.ready = true;&lt;br /&gt;
					// Call all registered handlers, and clear the array.&lt;br /&gt;
					Array.forEach( readyEvent, function ( f, idx ) {&lt;br /&gt;
						try { f(); } catch ( ex ) {}&lt;br /&gt;
						readyEvent[ idx ] = null;&lt;br /&gt;
					} );&lt;br /&gt;
					readyEvent = null;&lt;br /&gt;
				};&lt;br /&gt;
&lt;br /&gt;
				ImageAnnotator.UI.addReadyEventHandler = function ( f ) {&lt;br /&gt;
					if ( ImageAnnotator.UI.ready ) {&lt;br /&gt;
						f(); // Already fired: call directly&lt;br /&gt;
					} else {&lt;br /&gt;
						readyEvent[ readyEvent.length ] = f;&lt;br /&gt;
					}&lt;br /&gt;
				};&lt;br /&gt;
&lt;br /&gt;
				ImageAnnotator.UI.setup = function () {&lt;br /&gt;
					if ( ImageAnnotator.UI.repo ) { return; }&lt;br /&gt;
					var self = ImageAnnotator.UI;&lt;br /&gt;
					var node = LAPI.make( &#039;div&#039;, null, { display: &#039;none&#039; } );&lt;br /&gt;
					document.body.appendChild( node );&lt;br /&gt;
					if ( typeof UIElements === &#039;undefined&#039; ) {&lt;br /&gt;
						self.basic = true;&lt;br /&gt;
						self.repo = {};&lt;br /&gt;
						for ( var item in self.defaults ) {&lt;br /&gt;
							node.innerHTML = self.defaults[ item ];&lt;br /&gt;
							self.repo[ item ] = node.firstChild;&lt;br /&gt;
							LAPI.DOM.removeChildren( node );&lt;br /&gt;
						}&lt;br /&gt;
					} else {&lt;br /&gt;
						self.basic = false;&lt;br /&gt;
						self.repo = UIElements.emptyRepository( self.defaultLanguage );&lt;br /&gt;
						for ( var item in self.defaults ) {&lt;br /&gt;
							node.innerHTML = self.defaults[ item ];&lt;br /&gt;
							UIElements.setEntry( item, self.repo, node.firstChild );&lt;br /&gt;
							LAPI.DOM.removeChildren( node );&lt;br /&gt;
						}&lt;br /&gt;
						UIElements.load( &#039;wpImageAnnotatorTexts&#039;, null, null, self.repo );&lt;br /&gt;
					}&lt;br /&gt;
					LAPI.DOM.removeNode( node );&lt;br /&gt;
				};&lt;br /&gt;
&lt;br /&gt;
				ImageAnnotator.UI.get = function ( id, basic, no_plea ) {&lt;br /&gt;
					var self = ImageAnnotator.UI;&lt;br /&gt;
					if ( !self.repo ) { self.setup(); }&lt;br /&gt;
					var result = null;&lt;br /&gt;
					var add_plea = false;&lt;br /&gt;
					if ( self.basic ) {&lt;br /&gt;
						result = self.repo[ id ];&lt;br /&gt;
					} else {&lt;br /&gt;
						result = UIElements.getEntry( id, self.repo, mw.config.get( &#039;wgUserLanguage&#039; ), null );&lt;br /&gt;
						add_plea = !result;&lt;br /&gt;
						if ( !result ) { result = UIElements.getEntry( id, self.repo ); }&lt;br /&gt;
					}&lt;br /&gt;
					self.needs_plea = add_plea;&lt;br /&gt;
					if ( !result ) { return null; } // Hmmm... what happened here? We normally have defaults...&lt;br /&gt;
					if ( basic ) { return LAPI.DOM.getInnerText( result ).trim(); }&lt;br /&gt;
					result = result.cloneNode( true );&lt;br /&gt;
					if ( mw.config.get( &#039;wgServer&#039; ).contains( &#039;/commons&#039; ) &amp;amp;&amp;amp; add_plea &amp;amp;&amp;amp; !no_plea ) {&lt;br /&gt;
						// Add a translation plea.&lt;br /&gt;
						if ( result.nodeName.toLowerCase() == &#039;div&#039; ) {&lt;br /&gt;
							result.appendChild( self.get_plea() );&lt;br /&gt;
						} else {&lt;br /&gt;
							var span = LAPI.make( &#039;span&#039; );&lt;br /&gt;
							span.appendChild( result );&lt;br /&gt;
							span.appendChild( self.get_plea() );&lt;br /&gt;
							result = span;&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
					return result;&lt;br /&gt;
				};&lt;br /&gt;
&lt;br /&gt;
				ImageAnnotator.UI.get_plea = function () {&lt;br /&gt;
					var self = ImageAnnotator.UI;&lt;br /&gt;
					var translate = self.get( &#039;wpTranslate&#039;, false, true ) || &#039;translate&#039;;&lt;br /&gt;
					var span = LAPI.make( &#039;small&#039; );&lt;br /&gt;
					span.appendChild( document.createTextNode( &#039;\xa0(&#039; ) );&lt;br /&gt;
					span.appendChild(&lt;br /&gt;
						LAPI.DOM.makeLink(&lt;br /&gt;
							mw.config.get( &#039;wgServer&#039; ) + mw.config.get( &#039;wgScript&#039; ) + &#039;?title=MediaWiki_talk:ImageAnnotatorTexts&#039; +&lt;br /&gt;
							&#039;&amp;amp;action=edit&amp;amp;section=new&amp;amp;withJS=MediaWiki:ImageAnnotatorTranslator.js&#039; +&lt;br /&gt;
							&#039;&amp;amp;language=&#039; + mw.config.get( &#039;wgUserLanguage&#039; ),&lt;br /&gt;
							translate,&lt;br /&gt;
							( typeof translate === &#039;string&#039; ? translate : LAPI.DOM.getInnerText( translate ).trim() )&lt;br /&gt;
						)&lt;br /&gt;
					);&lt;br /&gt;
					span.appendChild( document.createTextNode( &#039;)&#039; ) );&lt;br /&gt;
					return span;&lt;br /&gt;
				};&lt;br /&gt;
&lt;br /&gt;
				ImageAnnotator.UI.init = function ( html_text_or_json ) {&lt;br /&gt;
					var text;&lt;br /&gt;
					if ( typeof html_text_or_json === &#039;string&#039; ) {&lt;br /&gt;
						text = html_text_or_json;&lt;br /&gt;
					} else if (&lt;br /&gt;
						typeof html_text_or_json !== &#039;undefined&#039; &amp;amp;&amp;amp;&lt;br /&gt;
						typeof html_text_or_json.parse !== &#039;undefined&#039; &amp;amp;&amp;amp;&lt;br /&gt;
						typeof html_text_or_json.parse.text !== &#039;undefined&#039; &amp;amp;&amp;amp;&lt;br /&gt;
						typeof html_text_or_json.parse.text[ &#039;*&#039; ] !== &#039;undefined&#039;&lt;br /&gt;
					) {&lt;br /&gt;
						text = html_text_or_json.parse.text[ &#039;*&#039; ];&lt;br /&gt;
					} else {&lt;br /&gt;
						text = null;&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					if ( !text ) {&lt;br /&gt;
						ImageAnnotator.UI.fireReadyEvent();&lt;br /&gt;
						return;&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					var node = LAPI.make( &#039;div&#039;, null, { display: &#039;none&#039; } );&lt;br /&gt;
					document.body.appendChild( node );&lt;br /&gt;
					try {&lt;br /&gt;
						node.innerHTML = text;&lt;br /&gt;
					} catch ( ex ) {&lt;br /&gt;
						LAPI.DOM.removeNode( node );&lt;br /&gt;
						node = null;&lt;br /&gt;
						// Swallow. We&#039;ll just work with the default UI&lt;br /&gt;
					}&lt;br /&gt;
					if ( node &amp;amp;&amp;amp; !ImageAnnotator.UI.repo ) { ImageAnnotator.UI.setup(); }&lt;br /&gt;
					ImageAnnotator.UI.fireReadyEvent();&lt;br /&gt;
				};&lt;br /&gt;
&lt;br /&gt;
				var ui_page = &#039;{{MediaWiki:ImageAnnotatorTexts&#039; +&lt;br /&gt;
				( mw.config.get( &#039;wgUserLanguage&#039; ) != mw.config.get( &#039;wgContentLanguage&#039; ) ? &#039;|lang=&#039; + mw.config.get( &#039;wgUserLanguage&#039; ) : &#039;&#039; ) +&lt;br /&gt;
				&#039;|live=1}}&#039;;&lt;br /&gt;
&lt;br /&gt;
				function get_ui_no_ajax() {&lt;br /&gt;
					var url =&lt;br /&gt;
						mw.config.get( &#039;wgServer&#039; ) + mw.config.get( &#039;wgScriptPath&#039; ) + &#039;/api.php?action=parse&amp;amp;pst&amp;amp;text=&#039; +&lt;br /&gt;
						encodeURIComponent( ui_page ) + &#039;&amp;amp;title=API&amp;amp;prop=text&amp;amp;format=json&#039; +&lt;br /&gt;
						&#039;&amp;amp;callback=ImageAnnotator.UI.init&amp;amp;maxage=14400&amp;amp;smaxage=14400&#039;;&lt;br /&gt;
					// Result cached for 4 hours. How to properly handle an error? It appears there&#039;s no way to catch&lt;br /&gt;
					// that on IE. (On FF, we could use an onerror handler on the script tag, but on FF, we use Ajax&lt;br /&gt;
					// anyway.)&lt;br /&gt;
					IA.getScript( url, true ); // No local caching!&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				function get_ui() {&lt;br /&gt;
					IA.haveAjax = ( LAPI.Ajax.getRequest() != null );&lt;br /&gt;
					IA.ajaxQueried = true;&lt;br /&gt;
&lt;br /&gt;
					// Works only with Ajax (but then, most of this script doesn&#039;t work without).&lt;br /&gt;
					// Check what this does to load times... If lots of people used this, it might be better to&lt;br /&gt;
					// have the UI texts included in some footer as we did on Special:Upload. True, everybody&lt;br /&gt;
					// would get the texts, even people not using this, but the texts are small anyway...&lt;br /&gt;
					if ( !IA.haveAjax ) {&lt;br /&gt;
						get_ui_no_ajax(); // Fallback.&lt;br /&gt;
						return;&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					LAPI.Ajax.parseWikitext(&lt;br /&gt;
						ui_page,&lt;br /&gt;
						ImageAnnotator.UI.init,&lt;br /&gt;
						ImageAnnotator.UI.fireReadyEvent,&lt;br /&gt;
						false,&lt;br /&gt;
						null,&lt;br /&gt;
						&#039;API&#039;, // A fixed string to enable caching at all.&lt;br /&gt;
						14400 // 4 hour caching.&lt;br /&gt;
					);&lt;br /&gt;
				} // end get_ui&lt;br /&gt;
&lt;br /&gt;
				if ( !window.XMLHttpRequest &amp;amp;&amp;amp; !!window.ActiveXObject ) {&lt;br /&gt;
					// IE has a stupid security setting asking whether ActiveX should be allowed. We avoid that&lt;br /&gt;
					// prompt by using getScript instead of parseWikitext in this case. The disadvantage&lt;br /&gt;
					// is that we don&#039;t do anything if this fails for some reason.&lt;br /&gt;
					get_ui_no_ajax();&lt;br /&gt;
				} else {&lt;br /&gt;
					get_ui();&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			setup_step_two: function () {&lt;br /&gt;
				var self = IA;&lt;br /&gt;
&lt;br /&gt;
				// Throw out any images for which we miss either the thumbnail or the full image size.&lt;br /&gt;
				// Also throws out thumbnails that are larger than the full image.&lt;br /&gt;
				self.imgs = Array.select( self.imgs, function ( elem, idx ) {&lt;br /&gt;
					var result =&lt;br /&gt;
						elem.thumb.width &amp;gt; 0 &amp;amp;&amp;amp; elem.thumb.height &amp;gt; 0 &amp;amp;&amp;amp;&lt;br /&gt;
						typeof elem.full_img !== &#039;undefined&#039; &amp;amp;&amp;amp;&lt;br /&gt;
						elem.full_img.width &amp;gt; 0 &amp;amp;&amp;amp; elem.full_img.height &amp;gt; 0 &amp;amp;&amp;amp;&lt;br /&gt;
						elem.full_img.width &amp;gt;= elem.thumb.width &amp;amp;&amp;amp;&lt;br /&gt;
						elem.full_img.height &amp;gt;= elem.thumb.height;&lt;br /&gt;
					if ( self.may_edit &amp;amp;&amp;amp; idx === 0 &amp;amp;&amp;amp; !result ) { self.may_edit = false; }&lt;br /&gt;
					return result;&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				if ( self.imgs.length === 0 ) { return; }&lt;br /&gt;
&lt;br /&gt;
				ImageAnnotator.UI.addReadyEventHandler( IA.complete_setup );&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			complete_setup: function () {&lt;br /&gt;
				// We can be sure to have the UI here because this is called only when the ready event of the&lt;br /&gt;
				// UI object is fired.&lt;br /&gt;
				var self = IA;&lt;br /&gt;
&lt;br /&gt;
				// Check edit permissions&lt;br /&gt;
				if ( self.may_edit &amp;amp;&amp;amp; mw.config.get( &#039;wgRestrictionEdit&#039; ) ) {&lt;br /&gt;
					self.may_edit = (&lt;br /&gt;
						( mw.config.get( &#039;wgRestrictionEdit&#039; ).length === 0 || mw.config.get( &#039;wgUserGroups&#039; ) &amp;amp;&amp;amp; mw.config.get( &#039;wgUserGroups&#039; ).join( &#039; &#039; ).contains( &#039;sysop&#039; ) ) ||&lt;br /&gt;
						(&lt;br /&gt;
							mw.config.get( &#039;wgRestrictionEdit&#039; ).length === 1 &amp;amp;&amp;amp; mw.config.get( &#039;wgRestrictionEdit&#039; )[ 0 ] === &#039;autoconfirmed&#039; &amp;amp;&amp;amp;&lt;br /&gt;
							mw.config.get( &#039;wgUserGroups&#039; ) &amp;amp;&amp;amp; mw.config.get( &#039;wgUserGroups&#039; ).join( &#039; &#039; ).contains( &#039;confirmed&#039; ) // confirmed &amp;amp; autoconfirmed&lt;br /&gt;
						)&lt;br /&gt;
					);&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				if ( self.may_edit ) {&lt;br /&gt;
					// Check whether the image is local. Don&#039;t allow editing if the file is remote.&lt;br /&gt;
					var sharedUpload = getElementsByClassName( document, &#039;div&#039;, &#039;sharedUploadNotice&#039; );&lt;br /&gt;
					self.may_edit = ( !sharedUpload || sharedUpload.length === 0 );&lt;br /&gt;
				}&lt;br /&gt;
				if ( self.may_edit &amp;amp;&amp;amp; mw.config.get( &#039;wgNamespaceNumber&#039; ) != 6 ) {&lt;br /&gt;
					// Only allow edits if the stored page name matches the current one.&lt;br /&gt;
					var img_page_name = getElementsByClassName( self.imgs[ 0 ].scope, &#039;*&#039;, &#039;wpImageAnnotatorPageName&#039; );&lt;br /&gt;
					if ( img_page_name &amp;amp;&amp;amp; img_page_name.length ) { img_page_name = LAPI.DOM.getInnerText( img_page_name[ 0 ] ); } else { img_page_name = &#039;&#039;; }&lt;br /&gt;
					self.may_edit = ( img_page_name.replace( / /g, &#039;_&#039; ) == mw.config.get( &#039;wgTitle&#039; ).replace( / /g, &#039;_&#039; ) );&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				if ( self.may_edit &amp;amp;&amp;amp; self.ajaxQueried ) { self.may_edit = self.haveAjax; }&lt;br /&gt;
&lt;br /&gt;
				// Now create viewers for all images&lt;br /&gt;
				self.viewers = new Array( self.imgs.length );&lt;br /&gt;
				for ( var i = 0; i &amp;lt; self.imgs.length; i++ ) {&lt;br /&gt;
					self.viewers[ i ] = new ImageNotesViewer( self.imgs[ i ], i === 0 &amp;amp;&amp;amp; self.may_edit );&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				if ( self.may_edit ) {&lt;br /&gt;
&lt;br /&gt;
					// Respect user override for zoom, if any&lt;br /&gt;
					self.zoom_threshold = ImageAnnotator_config.zoom_threshold;&lt;br /&gt;
					if (&lt;br /&gt;
						typeof window.ImageAnnotator_zoom_threshold !== &#039;undefined&#039; &amp;amp;&amp;amp;&lt;br /&gt;
						!isNaN( window.ImageAnnotator_zoom_threshold ) &amp;amp;&amp;amp;&lt;br /&gt;
						window.ImageAnnotator_zoom_threshold &amp;gt;= 0.0&lt;br /&gt;
					) {&lt;br /&gt;
						// If somebody sets it to a nonsensical high value, that&#039;s his or her problem: there won&#039;t be any&lt;br /&gt;
						// zooming.&lt;br /&gt;
						self.zoom_threshold = window.ImageAnnotator_zoom_threshold;&lt;br /&gt;
					}&lt;br /&gt;
					// Adapt zoom threshold for small thumbnails or images with a very lopsided width/height ratio,&lt;br /&gt;
					// but only if we *can* zoom at least twice&lt;br /&gt;
					if (&lt;br /&gt;
						self.viewers[ 0 ].full_img.width &amp;gt; 300 &amp;amp;&amp;amp;&lt;br /&gt;
						Math.min( self.viewers[ 0 ].factors.dx, self.viewers[ 0 ].factors.dy ) &amp;gt;= 2.0&lt;br /&gt;
					) {&lt;br /&gt;
						if (&lt;br /&gt;
							self.viewers[ 0 ].thumb.width &amp;lt; 400 ||&lt;br /&gt;
							self.viewers[ 0 ].thumb.width / self.viewers[ 0 ].thumb.height &amp;gt; 2.0 ||&lt;br /&gt;
							self.viewers[ 0 ].thumb.height / self.viewers[ 0 ].thumb.width &amp;gt; 2.0&lt;br /&gt;
						) {&lt;br /&gt;
							self.zoom_threshold = 0; // Force zooming&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					self.editor = new ImageAnnotationEditor();&lt;br /&gt;
&lt;br /&gt;
					function track( evt ) {&lt;br /&gt;
						evt = evt || window.event;&lt;br /&gt;
						if ( self.is_adding ) { self.update_zoom( evt ); }&lt;br /&gt;
						if ( !self.is_tracking ) { return LAPI.Evt.kill( evt ); }&lt;br /&gt;
						var mouse_pos = LAPI.Pos.mousePosition( evt );&lt;br /&gt;
						if ( !LAPI.Pos.isWithin( self.cover, mouse_pos.x, mouse_pos.y ) ) { return; }&lt;br /&gt;
						var origin = LAPI.Pos.position( self.cover );&lt;br /&gt;
						// Make mouse pos relative to cover&lt;br /&gt;
						mouse_pos.x = mouse_pos.x - origin.x;&lt;br /&gt;
						mouse_pos.y = mouse_pos.y - origin.y;&lt;br /&gt;
						if ( mouse_pos.x &amp;gt;= self.base_x ) {&lt;br /&gt;
							self.definer.style.width = String( mouse_pos.x - self.base_x ) + &#039;px&#039;;&lt;br /&gt;
							self.definer.style.left = String( self.base_x ) + &#039;px&#039;;&lt;br /&gt;
						} else {&lt;br /&gt;
							self.definer.style.width = String( self.base_x - mouse_pos.x ) + &#039;px&#039;;&lt;br /&gt;
							self.definer.style.left = String( mouse_pos.x ) + &#039;px&#039;;&lt;br /&gt;
						}&lt;br /&gt;
						if ( mouse_pos.y &amp;gt;= self.base_y ) {&lt;br /&gt;
							self.definer.style.height = String( mouse_pos.y - self.base_y ) + &#039;px&#039;;&lt;br /&gt;
							self.definer.style.top = String( self.base_y ) + &#039;px&#039;;&lt;br /&gt;
						} else {&lt;br /&gt;
							self.definer.style.height = String( self.base_y - mouse_pos.y ) + &#039;px&#039;;&lt;br /&gt;
							self.definer.style.top = String( mouse_pos.y ) + &#039;px&#039;;&lt;br /&gt;
						}&lt;br /&gt;
						return LAPI.Evt.kill( evt );&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					function pause( evt ) {&lt;br /&gt;
						LAPI.Evt.remove( document, &#039;mousemove&#039;, track, true );&lt;br /&gt;
						if ( !LAPI.Browser.is_ie &amp;amp;&amp;amp; typeof document.captureEvents === &#039;function&#039; ) { document.captureEvents( null ); }&lt;br /&gt;
						self.move_listening = false;&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					function resume( evt ) {&lt;br /&gt;
						// captureEvents is actually deprecated, but I haven&#039;t succeeded to make this work with&lt;br /&gt;
						// addEventListener only.&lt;br /&gt;
						if ( ( self.is_tracking || self.is_adding ) &amp;amp;&amp;amp; !self.move_listening ) {&lt;br /&gt;
							if ( !LAPI.Browser.is_ie &amp;amp;&amp;amp; typeof document.captureEvents === &#039;function&#039; ) { document.captureEvents( Event.MOUSEMOVE ); }&lt;br /&gt;
							LAPI.Evt.attach( document, &#039;mousemove&#039;, track, true );&lt;br /&gt;
							self.move_listening = true;&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					function stop_tracking( evt ) {&lt;br /&gt;
						evt = evt || window.event;&lt;br /&gt;
						// Check that we&#039;re within the image. Note: this check can fail only on IE &amp;gt;= 7, on other&lt;br /&gt;
						// browsers, we attach the handler on self.cover and thus we don&#039;t even get events outside&lt;br /&gt;
						// that range.&lt;br /&gt;
						var mouse_pos = LAPI.Pos.mousePosition( evt );&lt;br /&gt;
						if ( !LAPI.Pos.isWithin( self.cover, mouse_pos.x, mouse_pos.y ) ) { return; }&lt;br /&gt;
						if ( self.is_tracking ) {&lt;br /&gt;
							self.is_tracking = false;&lt;br /&gt;
							self.is_adding = false;&lt;br /&gt;
							// Done.&lt;br /&gt;
							pause();&lt;br /&gt;
							if ( LAPI.Browser.is_ie ) {&lt;br /&gt;
								// Trust Microsoft to get everything wrong!&lt;br /&gt;
								LAPI.Evt.remove( document, &#039;mouseup&#039;, stop_tracking );&lt;br /&gt;
							} else {&lt;br /&gt;
								LAPI.Evt.remove( self.cover, &#039;mouseup&#039;, stop_tracking );&lt;br /&gt;
							}&lt;br /&gt;
							LAPI.Evt.remove( window, &#039;blur&#039;, pause );&lt;br /&gt;
							LAPI.Evt.remove( window, &#039;focus&#039;, resume );&lt;br /&gt;
							self.cover.style.cursor = &#039;auto&#039;;&lt;br /&gt;
							LAPI.DOM.removeNode( self.border );&lt;br /&gt;
							LAPI.Evt.remove( self.cover, self.mouse_in, self.update_zoom_evt );&lt;br /&gt;
							LAPI.Evt.remove( self.cover, self.mouse_out, self.hide_zoom_evt );&lt;br /&gt;
							self.hide_zoom();&lt;br /&gt;
							self.viewers[ 0 ].hide(); // Hide all existing boxes&lt;br /&gt;
							if ( !self.definer || self.definer.offsetWidth &amp;lt;= 0 || self.definer.offsetHeight &amp;lt;= 0 ) {&lt;br /&gt;
								// Nothing: just remove the definer:&lt;br /&gt;
								if ( self.definer ) { LAPI.DOM.removeNode( self.definer ); }&lt;br /&gt;
								// Re-attach event handlers&lt;br /&gt;
								self.viewers[ 0 ].setShowHideEvents( true );&lt;br /&gt;
								self.hide_cover();&lt;br /&gt;
								self.viewers[ 0 ].setDefaultMsg();&lt;br /&gt;
								// And make sure we get the real view again&lt;br /&gt;
								self.viewers[ 0 ].show();&lt;br /&gt;
							} else {&lt;br /&gt;
								// We have a div with some extent: remove event capturing and create a new annotation&lt;br /&gt;
								var new_note = new ImageAnnotation( self.definer, self.viewers[ 0 ], -1 );&lt;br /&gt;
								self.viewers[ 0 ].register( new_note );&lt;br /&gt;
								self.editor.editNote( new_note );&lt;br /&gt;
							}&lt;br /&gt;
							self.definer = null;&lt;br /&gt;
						}&lt;br /&gt;
						if ( evt ) { return LAPI.Evt.kill( evt ); }&lt;br /&gt;
						return false;&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					function start_tracking( evt ) {&lt;br /&gt;
						if ( !self.is_tracking ) {&lt;br /&gt;
							self.is_tracking = true;&lt;br /&gt;
							evt = evt || window.event;&lt;br /&gt;
							// Set the position, size 1&lt;br /&gt;
							var mouse_pos = LAPI.Pos.mousePosition( evt );&lt;br /&gt;
							var origin = LAPI.Pos.position( self.cover );&lt;br /&gt;
							self.base_x = mouse_pos.x - origin.x;&lt;br /&gt;
							self.base_y = mouse_pos.y - origin.y;&lt;br /&gt;
							Object.merge(&lt;br /&gt;
								{ left: String( self.base_x ) + &#039;px&#039;,&lt;br /&gt;
									top: String( self.base_y ) + &#039;px&#039;,&lt;br /&gt;
									width: &#039;0px&#039;,&lt;br /&gt;
									height: &#039;0px&#039;,&lt;br /&gt;
									display: &#039;&#039;&lt;br /&gt;
								}&lt;br /&gt;
								, self.definer.style&lt;br /&gt;
							);&lt;br /&gt;
							// Set mouse handlers&lt;br /&gt;
							LAPI.Evt.remove( self.cover, &#039;mousedown&#039;, start_tracking );&lt;br /&gt;
							if ( LAPI.Browser.is_ie ) {&lt;br /&gt;
								LAPI.Evt.attach( document, &#039;mouseup&#039;, stop_tracking ); // Doesn&#039;t work properly on self.cover...&lt;br /&gt;
							} else {&lt;br /&gt;
								LAPI.Evt.attach( self.cover, &#039;mouseup&#039;, stop_tracking );&lt;br /&gt;
							}&lt;br /&gt;
							resume();&lt;br /&gt;
							LAPI.Evt.attach( window, &#039;blur&#039;, pause );&lt;br /&gt;
							LAPI.Evt.attach( window, &#039;focus&#039;, resume );&lt;br /&gt;
						}&lt;br /&gt;
						if ( evt ) { return LAPI.Evt.kill( evt ); }&lt;br /&gt;
						return false;&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					function add_new( evt ) {&lt;br /&gt;
						if ( !self.canEdit() ) { return; }&lt;br /&gt;
&lt;br /&gt;
						self.editor.hide_editor();&lt;br /&gt;
						Tooltips.close();&lt;br /&gt;
						var cover = self.get_cover();&lt;br /&gt;
						cover.style.cursor = &#039;crosshair&#039;;&lt;br /&gt;
						self.definer = LAPI.make(&lt;br /&gt;
							&#039;div&#039;, null,&lt;br /&gt;
							{&lt;br /&gt;
								border: &#039;1px solid &#039; + IA.new_border,&lt;br /&gt;
								display: &#039;none&#039;,&lt;br /&gt;
								position: &#039;absolute&#039;,&lt;br /&gt;
								top: &#039;0px&#039;,&lt;br /&gt;
								left: &#039;0px&#039;,&lt;br /&gt;
								width: &#039;0px&#039;,&lt;br /&gt;
								height: &#039;0px&#039;,&lt;br /&gt;
								padding: &#039;0&#039;,&lt;br /&gt;
								lineHeight: &#039;0px&#039;, // IE needs this, even though there are no lines within&lt;br /&gt;
								fontSize: &#039;0px&#039;, // IE&lt;br /&gt;
								zIndex: cover.style.zIndex - 2 // Below the mouse capture div&lt;br /&gt;
							}&lt;br /&gt;
						);&lt;br /&gt;
						self.viewers[ 0 ].img_div.appendChild( self.definer );&lt;br /&gt;
						// Enter mouse-tracking mode to define extent of view. Mouse cursor is outside of image,&lt;br /&gt;
						// hence none of our tooltips are visible.&lt;br /&gt;
						self.viewers[ 0 ].img_div.appendChild( self.border );&lt;br /&gt;
						self.show_cover();&lt;br /&gt;
						self.is_tracking = false;&lt;br /&gt;
						self.is_adding = true;&lt;br /&gt;
						LAPI.Evt.attach( cover, &#039;mousedown&#039;, start_tracking );&lt;br /&gt;
						resume();&lt;br /&gt;
						self.button_div.style.display = &#039;none&#039;;&lt;br /&gt;
						// Remove the event listeners on the image: IE sometimes invokes them even when the image is covered&lt;br /&gt;
						self.viewers[ 0 ].setShowHideEvents( false );&lt;br /&gt;
						self.viewers[ 0 ].hide(); // Make sure notes are hidden&lt;br /&gt;
						self.viewers[ 0 ].toggle( true ); // Show all note rectangles (but only the dummies)&lt;br /&gt;
						self.update_zoom_evt = LAPI.Evt.makeListener( self, self.update_zoom );&lt;br /&gt;
						self.hide_zoom_evt = LAPI.Evt.makeListener( self, self.hide_zoom );&lt;br /&gt;
						self.show_zoom();&lt;br /&gt;
						LAPI.Evt.attach( cover, self.mouse_in, self.update_zoom_evt );&lt;br /&gt;
						LAPI.Evt.attach( cover, self.mouse_out, self.hide_zoom_evt );&lt;br /&gt;
						LAPI.DOM.removeChildren( self.viewers[ 0 ].msg );&lt;br /&gt;
						self.viewers[ 0 ].msg.appendChild( ImageAnnotator.UI.get( &#039;wpImageAnnotatorDrawRectMsg&#039;, false ) );&lt;br /&gt;
						self.viewers[ 0 ].msg.style.display = &#039;&#039;;&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					self.button_div = LAPI.make( &#039;div&#039; );&lt;br /&gt;
					self.viewers[ 0 ].main_div.appendChild( self.button_div );&lt;br /&gt;
					self.add_button = LAPI.DOM.makeButton(&lt;br /&gt;
						&#039;ImageAnnotationAddButton&#039;,&lt;br /&gt;
						ImageAnnotator.UI.get( &#039;wpImageAnnotatorAddButtonText&#039;, true ),&lt;br /&gt;
						add_new&lt;br /&gt;
					);&lt;br /&gt;
					var add_plea = ImageAnnotator.UI.needs_plea;&lt;br /&gt;
					self.button_div.appendChild( self.add_button );&lt;br /&gt;
					self.help_link = self.createHelpLink();&lt;br /&gt;
					if ( self.help_link ) {&lt;br /&gt;
						self.button_div.appendChild( document.createTextNode( &#039;\xa0&#039; ) );&lt;br /&gt;
						self.button_div.appendChild( self.help_link );&lt;br /&gt;
					}&lt;br /&gt;
					if ( add_plea &amp;amp;&amp;amp; mw.config.get( &#039;wgServer&#039; ).contains( &#039;/commons&#039; ) ) { self.button_div.appendChild( ImageAnnotator.UI.get_plea() ); }&lt;br /&gt;
&lt;br /&gt;
				} // end if may_edit&lt;br /&gt;
&lt;br /&gt;
				// Get the file description pages of thumbnails. Figure out for which viewers we need to do this.&lt;br /&gt;
				var cache = {};&lt;br /&gt;
				var get_local = [];&lt;br /&gt;
				var get_foreign = [];&lt;br /&gt;
				Array.forEach( self.viewers, function ( viewer, idx ) {&lt;br /&gt;
					if ( viewer.setup_done || viewer.isLocal &amp;amp;&amp;amp; !viewer.has_page ) { return; }&lt;br /&gt;
					// Handle only images that either are foreign or local and do have a page.&lt;br /&gt;
					if ( cache[ viewer.realName ] ) {&lt;br /&gt;
						cache[ viewer.realName ][ cache[ viewer.realName ].length ] = idx;&lt;br /&gt;
					} else {&lt;br /&gt;
						cache[ viewer.realName ] = [ idx ];&lt;br /&gt;
						if ( !viewer.has_page ) {&lt;br /&gt;
							get_foreign[ get_foreign.length ] = viewer.realName;&lt;br /&gt;
						} else {&lt;br /&gt;
							get_local[ get_local.length ] = viewer.realName;&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				if ( get_local.length === 0 &amp;amp;&amp;amp; get_foreign.length === 0 ) { return; }&lt;br /&gt;
&lt;br /&gt;
				// Now we have unique page names in the cache and in to_get. Go get the corresponding file&lt;br /&gt;
				// description pages. We make a series of simultaneous asynchronous calls to avoid hitting&lt;br /&gt;
				// API limits and to keep the URL length below the limit for the foreign_repo calls.&lt;br /&gt;
&lt;br /&gt;
				function make_calls( list, execute_call, url_limit ) {&lt;br /&gt;
					function composer( list, from, length, url_limit ) {&lt;br /&gt;
						function compose( list, from, length, url_limit ) {&lt;br /&gt;
							var text = &#039;&#039;;&lt;br /&gt;
							var done = 0;&lt;br /&gt;
							for ( var i = from; i &amp;lt; from + length; i++ ) {&lt;br /&gt;
								var new_text =&lt;br /&gt;
									&#039;&amp;lt;div class=&amp;quot;wpImageAnnotatorInlineImageWrapper&amp;quot; style=&amp;quot;display:none;&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
									&#039;&amp;lt;span class=&amp;quot;image_annotation_inline_name&amp;quot;&amp;gt;&#039; + list[ i ] + &#039;&amp;lt;/span&amp;gt;&#039; +&lt;br /&gt;
									&#039;{{:&#039; + list[ i ] + &#039;}}&#039; + // Leading dot to avoid getting links to the full images if we hit a parser limit&lt;br /&gt;
									&#039;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
								if ( url_limit ) {&lt;br /&gt;
									new_text = encodeURIComponent( new_text );&lt;br /&gt;
									if ( text.length &amp;amp;&amp;amp; ( text.length + new_text.length &amp;gt; url_limit ) ) { break; }&lt;br /&gt;
								}&lt;br /&gt;
								text = text + new_text;&lt;br /&gt;
								done++;&lt;br /&gt;
								// Additionally, limit the number of image pages to get: these can be large, and the server&lt;br /&gt;
								// may refuse to actually do the transclusions but may in that case include the full images&lt;br /&gt;
								// in the result, which would make us load the full images, which is desastrous if there are&lt;br /&gt;
								// many thumbs to large images on the page.&lt;br /&gt;
								if ( done == 5 ) { break; }&lt;br /&gt;
							}&lt;br /&gt;
							return { text: text, n: done };&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
						var param = compose( list, from, length, url_limit );&lt;br /&gt;
						execute_call( param.text );&lt;br /&gt;
						return param.n;&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					var start = 0, chunk = 0, to_do = list.length;&lt;br /&gt;
					while ( to_do &amp;gt; 0 ) {&lt;br /&gt;
						chunk = composer( list, start, Math.min( 50, to_do ), url_limit );&lt;br /&gt;
						to_do -= chunk;&lt;br /&gt;
						start += chunk;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				var divRE = /(&amp;lt;\s*div\b)|(&amp;lt;\/\s*div\s*&amp;gt;)/ig;&lt;br /&gt;
				var blockStart = &#039;&amp;lt;div class=&amp;quot;wpImageAnnotatorInlineImageWrapper&amp;quot;&#039;;&lt;br /&gt;
				var inlineNameEnd = &#039;&amp;lt;/span&amp;gt;&#039;;&lt;br /&gt;
				var noteStart = &#039;&amp;lt;div id=&amp;quot;image_annotation_note_&#039;;&lt;br /&gt;
				var noteControlRE = /&amp;lt;div\s*class=&amp;quot;(wpImageAnnotatorInlinedRules|image_annotation_colors&amp;quot;)(\S|\s)*?\/div&amp;gt;/g;&lt;br /&gt;
&lt;br /&gt;
				// Our parse request returns the full html of the description pages&#039; contents, including any&lt;br /&gt;
				// license or information or other templates that we don&#039;t care about, and which may contain&lt;br /&gt;
				// additional images we&#039;d rather not load when we add this (X)HTML to the DOM. Therefore, we&lt;br /&gt;
				// strip out everything but the notes.&lt;br /&gt;
				function strip_noise( html ) {&lt;br /&gt;
					var result = &#039;&#039;;&lt;br /&gt;
					var m;&lt;br /&gt;
					// First, get rid of HTML comments and scripts&lt;br /&gt;
					html = html.replace( /&amp;lt;!--(.|\s)*?--&amp;gt;/g, &#039;&#039; ).replace( /&amp;lt;script(.|\s)*?\/script&amp;gt;/g, &#039;&#039; );&lt;br /&gt;
					var i = html.indexOf( blockStart, idx ), idx = 0, l = html.length;&lt;br /&gt;
					// Now collect pages&lt;br /&gt;
					while ( idx &amp;lt; l &amp;amp;&amp;amp; i &amp;gt;= idx ) {&lt;br /&gt;
						var j = html.indexOf( inlineNameEnd, i + blockStart.length );&lt;br /&gt;
						if ( j &amp;lt; i + blockStart.length ) { break; }&lt;br /&gt;
						result += html.substring( i, j + inlineNameEnd.length );&lt;br /&gt;
						idx = j + inlineNameEnd.length;&lt;br /&gt;
						// Now collect all image image notes for that page&lt;br /&gt;
						var note_begin = 0, next_block = html.indexOf( blockStart, idx );&lt;br /&gt;
						// Do we have image note control or color templates?&lt;br /&gt;
						j = idx;&lt;br /&gt;
						for ( ;; ) {&lt;br /&gt;
							noteControlRE.lastIndex = j;&lt;br /&gt;
							m = noteControlRE.exec( html );&lt;br /&gt;
							if ( !m || next_block &amp;gt;= idx &amp;amp;&amp;amp; m.index &amp;gt; next_block ) { break; }&lt;br /&gt;
							result += m[ 0 ];&lt;br /&gt;
							j = m.index + m[ 0 ].length;&lt;br /&gt;
						}&lt;br /&gt;
						// Collect notes&lt;br /&gt;
						for ( ;; ) {&lt;br /&gt;
							note_begin = html.indexOf( noteStart, idx );&lt;br /&gt;
							// Check whether next wrapper comes first&lt;br /&gt;
							if ( note_begin &amp;lt; idx || ( next_block &amp;gt;= idx &amp;amp;&amp;amp; note_begin &amp;gt; next_block ) ) { break; }&lt;br /&gt;
							// Start parsing nested &amp;lt;div&amp;gt; and &amp;lt;/div&amp;gt;, from note_begin on. Just ignore any other tags.&lt;br /&gt;
							var level = 1, k = note_begin + noteStart.length;&lt;br /&gt;
							while ( level &amp;gt; 0 &amp;amp;&amp;amp; k &amp;lt; l ) {&lt;br /&gt;
								divRE.lastIndex = k;&lt;br /&gt;
								m = divRE.exec( html );&lt;br /&gt;
								if ( !m || m.length &amp;lt; 2 ) {&lt;br /&gt;
									k = l; // Nothing found at all?&lt;br /&gt;
								} else {&lt;br /&gt;
									if ( m[ 1 ] ) {&lt;br /&gt;
										level++; k = m.index + m[ 1 ].length; // divStart found first&lt;br /&gt;
									} else if ( m.length &amp;gt; 2 &amp;amp;&amp;amp; m[ 2 ] ) {&lt;br /&gt;
										level--; k = m.index + m[ 2 ].length; // divEnd found first&lt;br /&gt;
									} else {&lt;br /&gt;
										k = l; // Huh?&lt;br /&gt;
									}&lt;br /&gt;
								}&lt;br /&gt;
							} // end loop for nested divs&lt;br /&gt;
							result += html.substring( note_begin, k );&lt;br /&gt;
							while ( level-- &amp;gt; 0 ) { result += &#039;&amp;lt;/div&amp;gt;&#039;; } // Missing ends.&lt;br /&gt;
							idx = k;&lt;br /&gt;
						} // end loop collecting notes&lt;br /&gt;
						result += &#039;&amp;lt;/div&amp;gt;&#039;; // Close the wrapper&lt;br /&gt;
						i = next_block;&lt;br /&gt;
					} // end loop collecting pages&lt;br /&gt;
					return result;&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				function setup_thumb_viewers( html_text ) {&lt;br /&gt;
					var node = LAPI.make( &#039;div&#039;, null, { display: &#039;none&#039; } );&lt;br /&gt;
					document.body.appendChild( node );&lt;br /&gt;
					try {&lt;br /&gt;
						node.innerHTML = strip_noise( html_text );&lt;br /&gt;
						var pages = getElementsByClassName( node, &#039;div&#039;, &#039;wpImageAnnotatorInlineImageWrapper&#039; );&lt;br /&gt;
						for ( var i = 0; pages &amp;amp;&amp;amp; i &amp;lt; pages.length; i++ ) {&lt;br /&gt;
							var notes = getElementsByClassName( pages[ i ], &#039;div&#039;, self.annotation_class );&lt;br /&gt;
							if ( !notes || notes.length === 0 ) {&lt;br /&gt;
								continue;&lt;br /&gt;
							}&lt;br /&gt;
							var page = self.getItem( &#039;inline_name&#039;, pages[ i ] );&lt;br /&gt;
							if ( !page ) { continue; }&lt;br /&gt;
							page = page.replace( / /g, &#039;_&#039; );&lt;br /&gt;
							var viewers = cache[ page ] || cache[ &#039;File:&#039; + page.substring( page.indexOf( &#039;:&#039; ) + 1 ) ];&lt;br /&gt;
							if ( !viewers || viewers.length === 0 ) {&lt;br /&gt;
								continue;&lt;br /&gt;
							}&lt;br /&gt;
							// Update rules.&lt;br /&gt;
							var rules = getElementsByClassName( pages[ i ], &#039;div&#039;, &#039;wpImageAnnotatorInlinedRules&#039; );&lt;br /&gt;
							var local_rules = {&lt;br /&gt;
								inline: Object.clone( IA.rules.inline ),&lt;br /&gt;
								thumbs: Object.clone( IA.rules.thumbs )&lt;br /&gt;
							};&lt;br /&gt;
							if ( rules &amp;amp;&amp;amp; rules.length ) {&lt;br /&gt;
								rules = rules[ 0 ];&lt;br /&gt;
								if (&lt;br /&gt;
									typeof local_rules.inline.show === &#039;undefined&#039; &amp;amp;&amp;amp;&lt;br /&gt;
									LAPI.DOM.hasClass( rules, &#039;wpImageAnnotatorNoInlineDisplay&#039; )&lt;br /&gt;
								) {&lt;br /&gt;
									local_rules.inline.show = false;&lt;br /&gt;
								}&lt;br /&gt;
								if (&lt;br /&gt;
									typeof local_rules.inline.icon === &#039;undefined&#039; &amp;amp;&amp;amp;&lt;br /&gt;
									LAPI.DOM.hasClass( rules, &#039;wpImageAnnotatorInlineDisplayIcon&#039; )&lt;br /&gt;
								) {&lt;br /&gt;
									local_rules.inline.icon = true;&lt;br /&gt;
								}&lt;br /&gt;
								if (&lt;br /&gt;
									typeof local_rules.thumbs.show === &#039;undefined&#039; &amp;amp;&amp;amp;&lt;br /&gt;
									LAPI.DOM.hasClass( rules, &#039;wpImageAnnotatorNoThumbs&#039; )&lt;br /&gt;
								) {&lt;br /&gt;
									local_rules.thumbs.show = false;&lt;br /&gt;
								}&lt;br /&gt;
								if (&lt;br /&gt;
									typeof local_rules.thumbs.icon === &#039;undefined&#039; &amp;amp;&amp;amp;&lt;br /&gt;
									LAPI.DOM.hasClass( rules, &#039;wpImageAnnotatorThumbDisplayIcon&#039; )&lt;br /&gt;
								) {&lt;br /&gt;
									local_rules.thumbs.icon = true;&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
							// Make sure all are set&lt;br /&gt;
							local_rules.inline.show =&lt;br /&gt;
								typeof local_rules.inline.show === &#039;undefined&#039; || local_rules.inline.show;&lt;br /&gt;
							local_rules.thumbs.show =&lt;br /&gt;
								typeof local_rules.thumbs.show === &#039;undefined&#039; || local_rules.thumbs.show;&lt;br /&gt;
							local_rules.inline.icon =&lt;br /&gt;
								typeof local_rules.inline.icon !== &#039;undefined&#039; &amp;amp;&amp;amp; local_rules.inline.icon;&lt;br /&gt;
							local_rules.thumbs.icon =&lt;br /&gt;
								typeof local_rules.thumbs.icon !== &#039;undefined&#039; &amp;amp;&amp;amp; local_rules.thumbs.icon;&lt;br /&gt;
							if ( !local_rules.inline.show ) { continue; }&lt;br /&gt;
							// Now use pages[i] as a scope shared by all the viewers using it. Since we clone note&lt;br /&gt;
							// contents for note display, this works. Otherwise, we&#039;d have to copy the notes into&lt;br /&gt;
							// each viewer&#039;s scope.&lt;br /&gt;
							document.body.appendChild( pages[ i ] ); // Move it out of &#039;node&#039;&lt;br /&gt;
							// Set viewers&#039; scopes and finish their setup.&lt;br /&gt;
							Array.forEach( viewers, function ( v ) {&lt;br /&gt;
								if ( !self.viewers[ v ].isThumbnail || local_rules.thumbs.show ) {&lt;br /&gt;
									self.viewers[ v ].scope = pages[ i ];&lt;br /&gt;
									self.viewers[ v ].setup( self.viewers[ v ].isThumbnail &amp;amp;&amp;amp; local_rules.thumbs.icon ||&lt;br /&gt;
									self.viewers[ v ].isOther &amp;amp;&amp;amp; local_rules.inline.icon );&lt;br /&gt;
								}&lt;br /&gt;
							} );&lt;br /&gt;
						}&lt;br /&gt;
					} catch ( ex ) {}&lt;br /&gt;
					LAPI.DOM.removeNode( node );&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				ImageAnnotator.script_callbacks = [];&lt;br /&gt;
&lt;br /&gt;
				function make_script_calls( list, api ) {&lt;br /&gt;
					var template = api + &#039;?action=parse&amp;amp;pst&amp;amp;text=&amp;amp;prop=text&amp;amp;format=json&#039; +&lt;br /&gt;
						&#039;&amp;amp;maxage=1800&amp;amp;smaxage=1800&amp;amp;uselang=&#039; + mw.config.get( &#039;wgUserLanguage&#039; ) + // see bugzilla 22764&lt;br /&gt;
						&#039;&amp;amp;callback=ImageAnnotator.script_callbacks[].callback&#039;;&lt;br /&gt;
					if ( template.startsWith( &#039;//&#039; ) ) { template = document.location.protocol + template; } // Avoid protocol-relative URIs (IE7 bug)&lt;br /&gt;
					make_calls(&lt;br /&gt;
						list,&lt;br /&gt;
						function ( text ) {&lt;br /&gt;
							var idx = ImageAnnotator.script_callbacks.length;&lt;br /&gt;
							ImageAnnotator.script_callbacks[ idx ] = {&lt;br /&gt;
								callback: function ( json ) {&lt;br /&gt;
									if ( json &amp;amp;&amp;amp; json.parse &amp;amp;&amp;amp; json.parse.text &amp;amp;&amp;amp; json.parse.text[ &#039;*&#039; ] ) {&lt;br /&gt;
										setup_thumb_viewers( json.parse.text[ &#039;*&#039; ] );&lt;br /&gt;
									}&lt;br /&gt;
									ImageAnnotator.script_callbacks[ idx ].done = true;&lt;br /&gt;
									if ( ImageAnnotator.script_callbacks[ idx ].script ) {&lt;br /&gt;
										LAPI.DOM.removeNode( ImageAnnotator.script_callbacks[ idx ].script );&lt;br /&gt;
										ImageAnnotator.script_callbacks[ idx ].script = null;&lt;br /&gt;
									}&lt;br /&gt;
								},&lt;br /&gt;
								done: false&lt;br /&gt;
							};&lt;br /&gt;
							ImageAnnotator.script_callbacks[ idx ].script =&lt;br /&gt;
								IA.getScript(&lt;br /&gt;
									template.replace( &#039;script_callbacks[].callback&#039;, &#039;script_callbacks[&#039; + idx + &#039;].callback&#039; )&lt;br /&gt;
										.replace( &#039;&amp;amp;text=&amp;amp;&#039;, &#039;&amp;amp;text=&#039; + text + &#039;&amp;amp;&#039; ),&lt;br /&gt;
									true // No local caching!&lt;br /&gt;
								);&lt;br /&gt;
							if (&lt;br /&gt;
								ImageAnnotator.script_callbacks &amp;amp;&amp;amp; ImageAnnotator.script_callbacks[ idx ] &amp;amp;&amp;amp;&lt;br /&gt;
								ImageAnnotator.script_callbacks[ idx ].done &amp;amp;&amp;amp; ImageAnnotator.script_callbacks[ idx ].script&lt;br /&gt;
							) {&lt;br /&gt;
								LAPI.DOM.removeNode( ImageAnnotator.script_callbacks[ idx ].script );&lt;br /&gt;
								ImageAnnotator.script_callbacks[ idx ].script = null;&lt;br /&gt;
							}&lt;br /&gt;
						},&lt;br /&gt;
						( LAPI.DOM.is_ie ? 1950 : 4000 ) - template.length // Some slack for caching parameters&lt;br /&gt;
					);&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				if ( ( !window.XMLHttpRequest &amp;amp;&amp;amp; !!window.ActiveXObject ) || !self.haveAjax ) {&lt;br /&gt;
					make_script_calls( get_local, mw.config.get( &#039;wgServer&#039; ) + mw.config.get( &#039;wgScriptPath&#039; ) + &#039;/api.php&#039; );&lt;br /&gt;
				} else {&lt;br /&gt;
					make_calls(&lt;br /&gt;
						get_local,&lt;br /&gt;
						function ( text ) {&lt;br /&gt;
							LAPI.Ajax.parseWikitext(&lt;br /&gt;
								text,&lt;br /&gt;
								function ( html_text ) { if ( html_text ) { setup_thumb_viewers( html_text ); } },&lt;br /&gt;
								function () {},&lt;br /&gt;
								false,&lt;br /&gt;
								null,&lt;br /&gt;
								&#039;API&#039;, // Fixed string to enable caching at all&lt;br /&gt;
								1800 // 30 minutes caching.&lt;br /&gt;
							);&lt;br /&gt;
						}&lt;br /&gt;
					);&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				// Can&#039;t use Ajax for foreign repo, might violate single-origin policy (e.g. from wikisource.org&lt;br /&gt;
				// to wikimedia.org). Attention, here we must care about the URL length! IE has a limit of 2083&lt;br /&gt;
				// character (2048 in the path part), and servers also may impose limits (on the WMF servers,&lt;br /&gt;
				// the limit appears to be 8kB).&lt;br /&gt;
				make_script_calls( get_foreign, ImageAnnotator_config.sharedRepositoryAPI() );&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			show_zoom: function () {&lt;br /&gt;
				var self = IA;&lt;br /&gt;
				if (&lt;br /&gt;
					(&lt;br /&gt;
						self.viewers[ 0 ].factors.dx &amp;lt; self.zoom_threshold &amp;amp;&amp;amp;&lt;br /&gt;
						self.viewers[ 0 ].factors.dy &amp;lt; self.zoom_threshold&lt;br /&gt;
					) ||&lt;br /&gt;
					Math.max( self.viewers[ 0 ].factors.dx, self.viewers[ 0 ].factors.dy ) &amp;lt; 2.0&lt;br /&gt;
				) {&lt;br /&gt;
					// Below zoom threshold, or full image not even twice the size of the preview&lt;br /&gt;
					return;&lt;br /&gt;
				}&lt;br /&gt;
				if ( !self.zoom ) {&lt;br /&gt;
					self.zoom = LAPI.make(&lt;br /&gt;
						&#039;div&#039;,&lt;br /&gt;
						{ id: &#039;image_annotator_zoom&#039; },&lt;br /&gt;
						{&lt;br /&gt;
							overflow: &#039;hidden&#039;,&lt;br /&gt;
							width: &#039;200px&#039;,&lt;br /&gt;
							height: &#039;200px&#039;,&lt;br /&gt;
							position: &#039;absolute&#039;,&lt;br /&gt;
							display: &#039;none&#039;,&lt;br /&gt;
							top: &#039;0px&#039;,&lt;br /&gt;
							left: &#039;0px&#039;,&lt;br /&gt;
							border: &#039;2px solid #666666&#039;,&lt;br /&gt;
							backgroundColor: &#039;white&#039;,&lt;br /&gt;
							zIndex: 2050 // On top of everything&lt;br /&gt;
						}&lt;br /&gt;
					);&lt;br /&gt;
					var src = self.viewers[ 0 ].img.getAttribute( &#039;src&#039;, 2 );&lt;br /&gt;
					// Adjust zoom_factor&lt;br /&gt;
					if ( self.zoom_factor &amp;gt; self.viewers[ 0 ].factors.dx || self.zoom_factor &amp;gt; self.viewers[ 0 ].factors.dy ) { self.zoom_factor = Math.min( self.viewers[ 0 ].factors.dx, self.viewers[ 0 ].factors.dy ); }&lt;br /&gt;
					self.zoom.appendChild( LAPI.make( &#039;div&#039;, null, { position: &#039;relative&#039; } ) );&lt;br /&gt;
					// Calculate zoom size and source link&lt;br /&gt;
					var zoom_width = Math.floor( self.viewers[ 0 ].thumb.width * self.zoom_factor );&lt;br /&gt;
					var zoom_height = Math.floor( self.viewers[ 0 ].thumb.height * self.zoom_factor );&lt;br /&gt;
					// For SVGs, always use a scaled PNG for the zoom.&lt;br /&gt;
					if ( zoom_width &amp;gt; 0.9 * self.viewers[ 0 ].full_img.width &amp;amp;&amp;amp; src.search( /\.svg\.png$/i ) &amp;lt; 0 ) {&lt;br /&gt;
						// If the thumb we&#039;d be loading was within about 80% of the full image size, we may just as&lt;br /&gt;
						// well get the full image instead of a scaled version.&lt;br /&gt;
						self.zoom_factor = Math.min( self.viewers[ 0 ].factors.dx, self.viewers[ 0 ].factors.dy );&lt;br /&gt;
						zoom_width = self.viewers[ 0 ].full_img.width;&lt;br /&gt;
						zoom_height = self.viewers[ 0 ].full_img.height;&lt;br /&gt;
					}&lt;br /&gt;
					// Construct the initial zoomed image. We need to clone; if we create a completely&lt;br /&gt;
					// new DOM node ourselves, it may not work on IE6...&lt;br /&gt;
					var zoomed = self.viewers[ 0 ].img.cloneNode( true );&lt;br /&gt;
					zoomed.width = String( zoom_width );&lt;br /&gt;
					zoomed.height = String( zoom_height );&lt;br /&gt;
					Object.merge( { position: &#039;absolute&#039;, top: &#039;0px&#039;, left: &#039;0px&#039; }, zoomed.style );&lt;br /&gt;
					self.zoom.firstChild.appendChild( zoomed );&lt;br /&gt;
					// Crosshair&lt;br /&gt;
					self.zoom.firstChild.appendChild(&lt;br /&gt;
						LAPI.make(&lt;br /&gt;
							&#039;div&#039;, null,&lt;br /&gt;
							{&lt;br /&gt;
								width: &#039;1px&#039;,&lt;br /&gt;
								height: &#039;200px&#039;,&lt;br /&gt;
								borderLeft: &#039;1px solid red&#039;,&lt;br /&gt;
								position: &#039;absolute&#039;,&lt;br /&gt;
								top: &#039;0px&#039;,&lt;br /&gt;
								left: &#039;100px&#039;&lt;br /&gt;
							}&lt;br /&gt;
						)&lt;br /&gt;
					);&lt;br /&gt;
					self.zoom.firstChild.appendChild(&lt;br /&gt;
						LAPI.make(&lt;br /&gt;
							&#039;div&#039;, null,&lt;br /&gt;
							{&lt;br /&gt;
								width: &#039;200px&#039;,&lt;br /&gt;
								height: &#039;1px&#039;,&lt;br /&gt;
								borderTop: &#039;1px solid red&#039;,&lt;br /&gt;
								position: &#039;absolute&#039;,&lt;br /&gt;
								top: &#039;100px&#039;,&lt;br /&gt;
								left: &#039;0px&#039;&lt;br /&gt;
							}&lt;br /&gt;
						)&lt;br /&gt;
					);&lt;br /&gt;
					document.body.appendChild( self.zoom );&lt;br /&gt;
					LAPI.DOM.loadImage(&lt;br /&gt;
						self.viewers[ 0 ].imgName,&lt;br /&gt;
						src,&lt;br /&gt;
						zoom_width,&lt;br /&gt;
						zoom_height,&lt;br /&gt;
						ImageAnnotator_config.thumbnailsGeneratedAutomatically(),&lt;br /&gt;
						function ( img ) {&lt;br /&gt;
							// Replace the image in self.zoom by self.zoom_loader, making sure we keep the offsets&lt;br /&gt;
							img.style.position = &#039;absolute&#039;;&lt;br /&gt;
							img.style.top = self.zoom.firstChild.firstChild.style.top;&lt;br /&gt;
							img.style.left = self.zoom.firstChild.firstChild.style.left;&lt;br /&gt;
							img.style.display = &#039;&#039;;&lt;br /&gt;
							self.zoom.firstChild.replaceChild( img, self.zoom.firstChild.firstChild );&lt;br /&gt;
						}&lt;br /&gt;
					);&lt;br /&gt;
				}&lt;br /&gt;
				self.zoom.style.display = &#039;none&#039;; // Will be shown in update&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			update_zoom: function ( evt ) {&lt;br /&gt;
				if ( !evt ) { return; } // We need an event to calculate positions!&lt;br /&gt;
				var self = IA;&lt;br /&gt;
				if ( !self.zoom ) { return; }&lt;br /&gt;
				var mouse_pos = LAPI.Pos.mousePosition( evt );&lt;br /&gt;
				var origin = LAPI.Pos.position( self.cover );&lt;br /&gt;
				if ( !LAPI.Pos.isWithin( self.cover, mouse_pos.x, mouse_pos.y ) ) {&lt;br /&gt;
					IA.hide_zoom();&lt;br /&gt;
					return;&lt;br /&gt;
				}&lt;br /&gt;
				var dx = mouse_pos.x - origin.x;&lt;br /&gt;
				var dy = mouse_pos.y - origin.y;&lt;br /&gt;
				// dx, dy is the offset within the preview image. Align the zoom image accordingly.&lt;br /&gt;
				var top = -dy * self.zoom_factor + 100;&lt;br /&gt;
				var left = -dx * self.zoom_factor + 100;&lt;br /&gt;
				self.zoom.firstChild.firstChild.style.top = String( top ) + &#039;px&#039;;&lt;br /&gt;
				self.zoom.firstChild.firstChild.style.left = String( left ) + &#039;px&#039;;&lt;br /&gt;
				self.zoom.style.top = mouse_pos.y + 10 + &#039;px&#039;; // Right below the mouse pointer&lt;br /&gt;
				// Horizontally keep it in view.&lt;br /&gt;
				var x = ( self.is_rtl ? mouse_pos.x - 10 : mouse_pos.x + 10 );&lt;br /&gt;
				if ( x &amp;lt; 0 ) { x = 0; }&lt;br /&gt;
				self.zoom.style.left = x + &#039;px&#039;;&lt;br /&gt;
				self.zoom.style.display = &#039;&#039;;&lt;br /&gt;
				// Now that we have offsetWidth, correct the position.&lt;br /&gt;
				if ( self.is_rtl ) {&lt;br /&gt;
					x = mouse_pos.x - 10 - self.zoom.offsetWidth;&lt;br /&gt;
					if ( x &amp;lt; 0 ) { x = 0; }&lt;br /&gt;
				} else {&lt;br /&gt;
					var off = LAPI.Pos.scrollOffset();&lt;br /&gt;
					var view = LAPI.Pos.viewport();&lt;br /&gt;
					if ( x + self.zoom.offsetWidth &amp;gt; off.x + view.x ) { x = off.x + view.x - self.zoom.offsetWidth; }&lt;br /&gt;
					if ( x &amp;lt; 0 ) { x = 0; }&lt;br /&gt;
				}&lt;br /&gt;
				self.zoom.style.left = x + &#039;px&#039;;&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			hide_zoom: function ( evt ) {&lt;br /&gt;
				if ( !IA.zoom ) { return; }&lt;br /&gt;
				if ( evt ) {&lt;br /&gt;
					var mouse_pos = LAPI.Pos.mousePosition( evt );&lt;br /&gt;
					if ( LAPI.Pos.isWithin( IA.cover, mouse_pos.x, mouse_pos.y ) ) { return; }&lt;br /&gt;
				}&lt;br /&gt;
				IA.zoom.style.display = &#039;none&#039;;&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			createHelpLink: function () {&lt;br /&gt;
				var msg = ImageAnnotator.UI.get( &#039;wpImageAnnotatorHelp&#039;, false, true );&lt;br /&gt;
				if ( !msg || !msg.lastChild ) { return null; }&lt;br /&gt;
				// Make sure we use the right protocol for all images:&lt;br /&gt;
				var imgs = msg.getElementsByTagName( &#039;img&#039; );&lt;br /&gt;
				var text;&lt;br /&gt;
				var tgt;&lt;br /&gt;
				if ( imgs ) {&lt;br /&gt;
					for ( var i = 0; i &amp;lt; imgs.length; i++ ) {&lt;br /&gt;
						var srcFixed = imgs[ i ].getAttribute( &#039;src&#039;, 2 ).replace( /^https?:/, document.location.protocol );&lt;br /&gt;
						imgs[ i ].src = srcFixed;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				if (&lt;br /&gt;
					msg.childNodes.length == 1 &amp;amp;&amp;amp;&lt;br /&gt;
					msg.firstChild.nodeName.toLowerCase() == &#039;a&#039; &amp;amp;&amp;amp;&lt;br /&gt;
					!LAPI.DOM.hasClass( msg.firstChild, &#039;image&#039; )&lt;br /&gt;
				) {&lt;br /&gt;
					msg.firstChild.id = &#039;ImageAnnotationHelpButton&#039;;&lt;br /&gt;
					return msg.firstChild; // Single link&lt;br /&gt;
				}&lt;br /&gt;
				// Otherwise, it&#039;s either a sequence of up to three images, or a span, followed by a&lt;br /&gt;
				// link.&lt;br /&gt;
				tgt = msg.lastChild;&lt;br /&gt;
				if ( tgt.nodeName.toLowerCase() != &#039;a&#039; ) { tgt = mw.config.get( &#039;wgServer&#039; ) + mw.config.get( &#039;wgArticlePath&#039; ).replace( &#039;$1&#039;, &#039;Help:Gadget-ImageAnnotator&#039; ); } else { tgt = tgt.href; }&lt;br /&gt;
&lt;br /&gt;
				function make_handler( tgt ) {&lt;br /&gt;
					var target = tgt;&lt;br /&gt;
					return function ( evt ) {&lt;br /&gt;
						var e = evt || window.event;&lt;br /&gt;
						location.href = target;&lt;br /&gt;
						if ( e ) { return LAPI.Evt.kill( e ); }&lt;br /&gt;
						return false;&lt;br /&gt;
					};&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				imgs = msg.getElementsByTagName( &#039;img&#039; );&lt;br /&gt;
&lt;br /&gt;
				if ( !imgs || !imgs.length ) {&lt;br /&gt;
					// We&#039;re supposed to have a spans giving the button text&lt;br /&gt;
					text = msg.firstChild;&lt;br /&gt;
					if ( text.nodeName.toLowerCase() === &#039;span&#039; ) { text = LAPI.DOM.getInnerText( text ); } else { text = &#039;Help&#039;; }&lt;br /&gt;
					return LAPI.DOM.makeButton(&lt;br /&gt;
						&#039;ImageAnnotationHelpButton&#039;&lt;br /&gt;
						, text&lt;br /&gt;
						, make_handler( tgt )&lt;br /&gt;
					);&lt;br /&gt;
				} else {&lt;br /&gt;
					return Buttons.makeButton( imgs, &#039;ImageAnnotationHelpButton&#039;, make_handler( tgt ) );&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			get_cover: function () {&lt;br /&gt;
				var self = IA;&lt;br /&gt;
				var shim;&lt;br /&gt;
				if ( !self.cover ) {&lt;br /&gt;
					var pos = { position: &#039;absolute&#039;,&lt;br /&gt;
						left: &#039;0px&#039;,&lt;br /&gt;
						top: &#039;0px&#039;,&lt;br /&gt;
						width: self.viewers[ 0 ].thumb.width + &#039;px&#039;,&lt;br /&gt;
						height: self.viewers[ 0 ].thumb.height + &#039;px&#039;&lt;br /&gt;
					};&lt;br /&gt;
					self.cover = LAPI.make( &#039;div&#039;, null, pos );&lt;br /&gt;
					self.border = self.cover.cloneNode( false );&lt;br /&gt;
					Object.merge(&lt;br /&gt;
						{ border: &#039;3px solid green&#039;, top: &#039;-3px&#039;, left: &#039;-3px&#039; }, self.border.style );&lt;br /&gt;
					self.cover.style.zIndex = 2000; // Above the tooltips&lt;br /&gt;
					if ( LAPI.Browser.is_ie ) {&lt;br /&gt;
						shim = LAPI.make( &#039;iframe&#039;, { frameBorder: 0, tabIndex: -1 }, pos );&lt;br /&gt;
						shim.style.filter = &#039;alpha(Opacity=0)&#039;; // Ensure transparency&lt;br /&gt;
						// Unfortunately, IE6/SP2 has a &amp;quot;security setting&amp;quot; called &amp;quot;Binary and script&lt;br /&gt;
						// behaviors&amp;quot;. If that is disabled, filters don&#039;t work, and our iframe would&lt;br /&gt;
						// appear as a white rectangle. Fix this by first placing the iframe just above&lt;br /&gt;
						// image (to block that windowed control) and then placing *another div* just&lt;br /&gt;
						// above that shim having the image as its background image.&lt;br /&gt;
						var imgZ = self.viewers[ 0 ].img.style.zIndex;&lt;br /&gt;
						if ( isNaN( imgZ ) ) { imgZ = 10; } // Arbitrary, positive, &amp;gt; 1, &amp;lt; 500&lt;br /&gt;
						shim.style.zIndex = imgZ + 1;&lt;br /&gt;
						self.ieFix = shim;&lt;br /&gt;
						// And now the bgImage div...&lt;br /&gt;
						shim = LAPI.make( &#039;div&#039;, null, pos );&lt;br /&gt;
						Object.merge(&lt;br /&gt;
							{ top: &#039;0px&#039;,&lt;br /&gt;
								backgroundImage: &#039;url(&#039; + self.viewers[ 0 ].img.src + &#039;)&#039;,&lt;br /&gt;
								zIndex: imgZ + 2&lt;br /&gt;
							}&lt;br /&gt;
							, shim.style&lt;br /&gt;
						);&lt;br /&gt;
						self.ieFix2 = shim;&lt;br /&gt;
					}&lt;br /&gt;
					if ( LAPI.Browser.is_opera ) {&lt;br /&gt;
						// It appears that events just pass through completely transparent divs on Opera.&lt;br /&gt;
						// Hence we have to ensure that these events are killed even if our cover doesn&#039;t&lt;br /&gt;
						// handle them.&lt;br /&gt;
						shim = LAPI.make( &#039;div&#039;, null, pos );&lt;br /&gt;
						shim.style.zIndex = self.cover.style.zIndex - 1;&lt;br /&gt;
						LAPI.Evt.attach( shim, &#039;mousemove&#039;,&lt;br /&gt;
							function ( evt ) { return LAPI.Evt.kill( evt || window.event ); } );&lt;br /&gt;
						LAPI.Evt.attach( shim, &#039;mousedown&#039;,&lt;br /&gt;
							function ( evt ) { return LAPI.Evt.kill( evt || window.event ); } );&lt;br /&gt;
						LAPI.Evt.attach( shim, &#039;mouseup&#039;,&lt;br /&gt;
							function ( evt ) { return LAPI.Evt.kill( evt || window.event ); } );&lt;br /&gt;
						shim.style.cursor = &#039;default&#039;;&lt;br /&gt;
						self.eventFix = shim;&lt;br /&gt;
					}&lt;br /&gt;
					self.cover_visible = false;&lt;br /&gt;
				}&lt;br /&gt;
				return self.cover;&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			show_cover: function () {&lt;br /&gt;
				var self = IA;&lt;br /&gt;
				if ( self.cover &amp;amp;&amp;amp; !self.cover_visible ) {&lt;br /&gt;
					if ( self.ieFix ) {&lt;br /&gt;
						self.viewers[ 0 ].img_div.appendChild( self.ieFix );&lt;br /&gt;
						self.viewers[ 0 ].img_div.appendChild( self.ieFix2 );&lt;br /&gt;
					}&lt;br /&gt;
					if ( self.eventFix ) { self.viewers[ 0 ].img_div.appendChild( self.eventFix ); }&lt;br /&gt;
					self.viewers[ 0 ].img_div.appendChild( self.cover );&lt;br /&gt;
					self.cover_visible = true;&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			hide_cover: function () {&lt;br /&gt;
				var self = IA;&lt;br /&gt;
				if ( self.cover &amp;amp;&amp;amp; self.cover_visible ) {&lt;br /&gt;
					if ( self.ieFix ) {&lt;br /&gt;
						LAPI.DOM.removeNode( self.ieFix );&lt;br /&gt;
						LAPI.DOM.removeNode( self.ieFix2 );&lt;br /&gt;
					}&lt;br /&gt;
					if ( self.eventFix ) { LAPI.DOM.removeNode( self.eventFix ); }&lt;br /&gt;
					LAPI.DOM.removeNode( self.cover );&lt;br /&gt;
					self.cover_visible = false;&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			getRawItem: function ( what, scope ) {&lt;br /&gt;
				var node = null;&lt;br /&gt;
				if ( !scope || scope == document ) {&lt;br /&gt;
					node = LAPI.$( &#039;image_annotation_&#039; + what );&lt;br /&gt;
				} else {&lt;br /&gt;
					node = getElementsByClassName( scope, &#039;*&#039;, &#039;image_annotation_&#039; + what );&lt;br /&gt;
					if ( node &amp;amp;&amp;amp; node.length ) { node = node[ 0 ]; } else { node = null; }&lt;br /&gt;
				}&lt;br /&gt;
				return node;&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			getItem: function ( what, scope ) {&lt;br /&gt;
				var node = IA.getRawItem( what, scope );&lt;br /&gt;
				if ( !node ) { return null; }&lt;br /&gt;
				return LAPI.DOM.getInnerText( node ).trim();&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			getIntItem: function ( what, scope ) {&lt;br /&gt;
				var x = IA.getItem( what, scope );&lt;br /&gt;
				if ( x !== null ) { x = parseInt( x, 10 ); }&lt;br /&gt;
				return x;&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			findNote: function ( text, id ) {&lt;br /&gt;
				function find( text, id, delim ) {&lt;br /&gt;
					var start = delim.start.replace( &#039;$1&#039;, id );&lt;br /&gt;
					var start_match = text.indexOf( start );&lt;br /&gt;
					if ( start_match &amp;lt; 0 ) { return null; }&lt;br /&gt;
					var end = delim.end.replace( &#039;$1&#039;, id );&lt;br /&gt;
					var end_match = text.indexOf( end );&lt;br /&gt;
					if ( end_match &amp;lt; start_match + start.length ) { return null; }&lt;br /&gt;
					return { start: start_match, end: end_match + end.length };&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				var result = null;&lt;br /&gt;
				for ( var i = 0; i &amp;lt; IA.note_delim.length &amp;amp;&amp;amp; !result; i++ ) {&lt;br /&gt;
					result = find( text, id, IA.note_delim[ i ] );&lt;br /&gt;
				}&lt;br /&gt;
				return result;&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			setWikitext: function ( pagetext ) {&lt;br /&gt;
				var self = IA;&lt;br /&gt;
				if ( self.wiki_read ) { return; }&lt;br /&gt;
				Array.forEach( self.viewers[ 0 ].annotations, function ( note ) {&lt;br /&gt;
					if ( note.model.id &amp;gt;= 0 ) {&lt;br /&gt;
						var span = self.findNote( pagetext, note.model.id );&lt;br /&gt;
						if ( !span ) { return; }&lt;br /&gt;
						// Now extract the wikitext&lt;br /&gt;
						var code = pagetext.substring( span.start, span.end );&lt;br /&gt;
						for ( var i = 0; i &amp;lt; self.note_delim.length; i++ ) {&lt;br /&gt;
							var start = self.note_delim[ i ].content_start.replace( &#039;$1&#039;, note.model.id );&lt;br /&gt;
							var end = self.note_delim[ i ].content_end.replace( &#039;$1&#039;, note.model.id );&lt;br /&gt;
							var j = code.indexOf( start );&lt;br /&gt;
							var k = code.indexOf( end );&lt;br /&gt;
							if ( j &amp;gt;= 0 &amp;amp;&amp;amp; k &amp;gt;= 0 &amp;amp;&amp;amp; k &amp;gt;= j + start.length ) {&lt;br /&gt;
								note.model.wiki = code.substring( j + start.length, k ).trim();&lt;br /&gt;
								return;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				} );&lt;br /&gt;
				self.wiki_read = true;&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			setSummary: function ( summary, initial_text, note_text ) {&lt;br /&gt;
				if ( initial_text.contains( &#039;$1&#039; ) ) {&lt;br /&gt;
					var max = ( summary.maxlength || 200 ) - initial_text.length;&lt;br /&gt;
					if ( note_text ) {&lt;br /&gt;
						initial_text =&lt;br /&gt;
							initial_text.replace( &#039;$1&#039;, &#039;: &#039; + note_text.replace( &#039;\n&#039;, &#039; &#039; ).substring( 0, max ) );&lt;br /&gt;
					} else {&lt;br /&gt;
						initial_text = initial_text.replace( &#039;$1&#039;, &#039;&#039; );&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				summary.value = initial_text;&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			getScript: function ( url, bypass_local_cache, bypass_caches ) {&lt;br /&gt;
				// Don&#039;t use LAPI here, it may not yet be available&lt;br /&gt;
				if ( bypass_caches ) {&lt;br /&gt;
					url += ( ( url.indexOf( &#039;?&#039; ) &amp;gt;= 0 ) ? &#039;&amp;amp;&#039; : &#039;?&#039; ) + &#039;dummyTimestamp=&#039; + ( new Date() ).getTime();&lt;br /&gt;
				}&lt;br /&gt;
				// Avoid protocol-relative URIs (IE7 bug)&lt;br /&gt;
				if ( url.length &amp;gt;= 2 &amp;amp;&amp;amp; url.substring( 0, 2 ) === &#039;//&#039; ) { url = document.location.protocol + url; }&lt;br /&gt;
				if ( bypass_local_cache ) {&lt;br /&gt;
					var s = document.createElement( &#039;script&#039; );&lt;br /&gt;
					s.setAttribute( &#039;src&#039;, url );&lt;br /&gt;
					s.setAttribute( &#039;type&#039;, &#039;text/javascript&#039; );&lt;br /&gt;
					document.getElementsByTagName( &#039;head&#039; )[ 0 ].appendChild( s );&lt;br /&gt;
					return s;&lt;br /&gt;
				} else {&lt;br /&gt;
					return mw.loader.load( url );&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			canEdit: function () {&lt;br /&gt;
				var self = IA;&lt;br /&gt;
				if ( self.may_edit ) {&lt;br /&gt;
					if ( !self.ajaxQueried ) {&lt;br /&gt;
						self.haveAjax = ( LAPI.Ajax.getRequest() != null );&lt;br /&gt;
						self.ajaxQueried = true;&lt;br /&gt;
						self.may_edit = self.haveAjax;&lt;br /&gt;
						if ( !self.may_edit &amp;amp;&amp;amp; self.button_div ) {&lt;br /&gt;
							LAPI.DOM.removeChildren( self.button_div );&lt;br /&gt;
							self.button_div.appendChild( ImageAnnotator.UI.get( &#039;wpImageAnnotatorCannotEditMsg&#039;, false ) );&lt;br /&gt;
							self.viewers[ 0 ].msg.style.display = &#039;&#039;;&lt;br /&gt;
							self.viewers[ 0 ].cannotEdit();&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				return self.may_edit;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
		}; // end IA&lt;br /&gt;
&lt;br /&gt;
		// Backwards compatibility&lt;br /&gt;
		function getElementsByClassName( scope, tag, className ) {&lt;br /&gt;
			if ( window.jQuery ) {&lt;br /&gt;
				return jQuery( scope ).find( ( ( !tag || tag === &#039;*&#039; ) ? &#039;&#039; : tag ) + &#039;.&#039; + className );&lt;br /&gt;
			} else {&lt;br /&gt;
				// For non-WMF wikis that might not have jQuery (yet), use the wikibits.js getElementsByClassName&lt;br /&gt;
				return getElementsByClassName( scope, tag, className );&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		window.ImageAnnotator = {&lt;br /&gt;
			install: function ( config ) { IA.install( config ); }&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		// Start it. Bypass caches; but allow for 4 hours client-side caching. Small file.&lt;br /&gt;
		IA.getScript(&lt;br /&gt;
			mw.config.get( &#039;wgScript&#039; ) + &#039;?title=MediaWiki:ImageAnnotatorConfig.js&amp;amp;action=raw&amp;amp;ctype=text/javascript&#039;,&lt;br /&gt;
			true // No local caching!&lt;br /&gt;
		);&lt;br /&gt;
&lt;br /&gt;
	}() ); // end local scope&lt;br /&gt;
&lt;br /&gt;
} // end if (guard against double inclusions)&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-ImageAnnotator&amp;diff=120529</id>
		<title>MediaWiki:Gadget-ImageAnnotator</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-ImageAnnotator&amp;diff=120529"/>
		<updated>2026-06-25T10:27:27Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[:commons:Help:Gadget-ImageAnnotator|ImageAnnotator]]: view image notes and comments on file description pages&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-GoogleTrans.js&amp;diff=120527</id>
		<title>MediaWiki:Gadget-GoogleTrans.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-GoogleTrans.js&amp;diff=120527"/>
		<updated>2026-06-25T10:27:13Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;//  _________________________________________________________________________________________&lt;br /&gt;
// |                                                                                         |&lt;br /&gt;
// |                    === WARNING: GLOBAL GADGET FILE ===                                  |&lt;br /&gt;
// |                  Changes to this page affect many users.                                |&lt;br /&gt;
// | Please discuss changes on the talk page or on [[Wikipedia_talk:Gadget]] before editing. |&lt;br /&gt;
// |_________________________________________________________________________________________|&lt;br /&gt;
//&lt;br /&gt;
// Translation tool that uses the &amp;quot;Google Translate&amp;quot; API.&lt;br /&gt;
// Opens a translation popup for selected text or word under the cursor when pushing the shift button.&lt;br /&gt;
&lt;br /&gt;
// imports [[User:Endo999/GoogleTrans.js]]&lt;br /&gt;
mw.loader.load(&#039;//en.wikipedia.org/w/index.php?title=User:Endo999/GoogleTrans.js&amp;amp;action=raw&amp;amp;ctype=text/javascript&#039;);&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-GoogleTrans&amp;diff=120525</id>
		<title>MediaWiki:Gadget-GoogleTrans</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-GoogleTrans&amp;diff=120525"/>
		<updated>2026-06-25T10:27:13Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;sup&amp;gt;&amp;lt;abbr title=&amp;quot;{{int:gadgets-external}}&amp;quot;&amp;gt;(E)&amp;lt;/abbr&amp;gt;&amp;lt;/sup&amp;gt; &amp;lt;sup&amp;gt;&amp;lt;abbr title=&amp;quot;{{int:gadgets-user}}&amp;quot;&amp;gt;(U)&amp;lt;/abbr&amp;gt;&amp;lt;/sup&amp;gt; [[User:Endo999/GoogleTrans|GoogleTrans]]: open a translation popup for the selected text or the word under the cursor when pushing the shift button&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-searchFocus.js&amp;diff=120523</id>
		<title>MediaWiki:Gadget-searchFocus.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-searchFocus.js&amp;diff=120523"/>
		<updated>2026-06-25T10:27:00Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;//  _________________________________________________________________________________________&lt;br /&gt;
// |                                                                                         |&lt;br /&gt;
// |                    === WARNING: GLOBAL GADGET FILE ===                                  |&lt;br /&gt;
// |                  Changes to this page affect many users.                                |&lt;br /&gt;
// | Please discuss changes on the talk page or on [[Wikipedia_talk:Gadget]] before editing. |&lt;br /&gt;
// |_________________________________________________________________________________________|&lt;br /&gt;
//&lt;br /&gt;
// Imported from [[Wikipedia:FAQ/Main Page]] as of April 1, 2008&lt;br /&gt;
&lt;br /&gt;
if ( mw.config.get( &#039;wgIsMainPage&#039; ) ) {&lt;br /&gt;
  $( function () {&lt;br /&gt;
    $( &#039;#searchInput&#039; ).focus();&lt;br /&gt;
  } );&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-searchFocus&amp;diff=120521</id>
		<title>MediaWiki:Gadget-searchFocus</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-searchFocus&amp;diff=120521"/>
		<updated>2026-06-25T10:26:59Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Focus the cursor in the search bar on loading the Main Page&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-exlinks.js&amp;diff=120519</id>
		<title>MediaWiki:Gadget-exlinks.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-exlinks.js&amp;diff=120519"/>
		<updated>2026-06-25T10:24:39Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// **********************************************************************&lt;br /&gt;
// **                 ***WARNING GLOBAL GADGET FILE***                 **&lt;br /&gt;
// **             changes to this file affect many users.              **&lt;br /&gt;
// **           please discuss on the talk page before editing         **&lt;br /&gt;
// **                                                                  **&lt;br /&gt;
// **********************************************************************&lt;br /&gt;
/**&lt;br /&gt;
 * @source mediawiki.org/wiki/Snippets/Open_external_links_in_new_window&lt;br /&gt;
 * @version 5&lt;br /&gt;
 */&lt;br /&gt;
mw.hook(&#039;wikipage.content&#039;).add(function($content) {&lt;br /&gt;
	// Second selector is for external links in Parsoid HTML+RDFa output (bug 65243).&lt;br /&gt;
	$content.find(&#039;a.external, a[rel=&amp;quot;mw:ExtLink&amp;quot;]&#039;).each(function () {&lt;br /&gt;
		// Can&#039;t use wgServer because it can be protocol relative&lt;br /&gt;
		// Use this.href property instead of this.getAttribute(&#039;href&#039;)  because the property&lt;br /&gt;
		// is converted to a full URL (including protocol)&lt;br /&gt;
		if (this.href.indexOf(location.protocol + &#039;//&#039; + location.hostname) !== 0) {&lt;br /&gt;
			this.target = &#039;_blank&#039;;&lt;br /&gt;
			if ( this.rel.indexOf( &#039;noopener&#039; ) &amp;lt; 0 ) {&lt;br /&gt;
				this.rel += &#039; noopener&#039;; // the leading space matters, rel attributes have space-separated tokens&lt;br /&gt;
			}&lt;br /&gt;
			if ( this.rel.indexOf( &#039;noreferrer&#039; ) &amp;lt; 0 ) {&lt;br /&gt;
				this.rel += &#039; noreferrer&#039;; // the leading space matters, rel attributes have space-separated tokens&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	});&lt;br /&gt;
});&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-exlinks&amp;diff=120517</id>
		<title>MediaWiki:Gadget-exlinks</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-exlinks&amp;diff=120517"/>
		<updated>2026-06-25T10:24:38Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Open external links in a new tab or window&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-removeAccessKeys.js&amp;diff=120515</id>
		<title>MediaWiki:Gadget-removeAccessKeys.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-removeAccessKeys.js&amp;diff=120515"/>
		<updated>2026-06-25T10:24:28Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// **********************************************************************&lt;br /&gt;
// **                 ***WARNING GLOBAL GADGET FILE***                 **&lt;br /&gt;
// **             changes to this file affect many users.              **&lt;br /&gt;
// **           please discuss on the talk page before editing         **&lt;br /&gt;
// **                                                                  **&lt;br /&gt;
// **********************************************************************&lt;br /&gt;
// Imported from version as of: 2007-04-17T22:22:27&lt;br /&gt;
// Deactivating access keys, see [[Wikipedia talk:WikiProject User scripts/Scripts/removeAccessKeys|talk page]]&lt;br /&gt;
jQuery(document).ready(function($) {&lt;br /&gt;
    if (mw.config.get(&#039;skin&#039;) == &#039;vector&#039;) {&lt;br /&gt;
        var head = document.getElementById(&#039;mw-head&#039;);&lt;br /&gt;
        if (head) removeKeys(head.getElementsByTagName(&#039;a&#039;));&lt;br /&gt;
        var panel = document.getElementById(&#039;mw-panel&#039;);&lt;br /&gt;
        if (panel) removeKeys(panel.getElementsByTagName(&#039;a&#039;));&lt;br /&gt;
    } else {&lt;br /&gt;
        var columnOne = document.getElementById(&#039;column-one&#039;);&lt;br /&gt;
        if (!columnOne) columnOne = document.getElementById(&#039;mw_portlets&#039;);&lt;br /&gt;
        if (!columnOne) return;&lt;br /&gt;
        removeKeys(columnOne.getElementsByTagName(&#039;a&#039;));&lt;br /&gt;
        var cactions = document.getElementById(&#039;p-cactions&#039;);&lt;br /&gt;
        if (cactions) removeKeys(cactions.getElementsByTagName(&#039;a&#039;));&lt;br /&gt;
        var personal = document.getElementById(&#039;p-personal&#039;);&lt;br /&gt;
        if (personal) removeKeys(personal.getElementsByTagName(&#039;a&#039;));&lt;br /&gt;
    }&lt;br /&gt;
    removeKeys(document.getElementsByTagName(&#039;input&#039;));&lt;br /&gt;
    removeKeys(document.getElementsByTagName(&#039;label&#039;));&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
function removeKeys(nodeList) {&lt;br /&gt;
    var el;&lt;br /&gt;
    for (var i = 0; i &amp;lt; nodeList.length; i++) {&lt;br /&gt;
        el = nodeList[i];&lt;br /&gt;
        if (!el.accessKey) continue;&lt;br /&gt;
        if (!window.removeAccessKeys || removeAccessKeys.indexOf(el.accessKey) &amp;gt;= 0) {&lt;br /&gt;
            el.accessKey = &#039;&#039;; // el.setAttribute(&#039;accessKey&#039;, &#039;&#039;); &lt;br /&gt;
            $(el).updateTooltipAccessKeys();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-removeAccessKeys&amp;diff=120513</id>
		<title>MediaWiki:Gadget-removeAccessKeys</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-removeAccessKeys&amp;diff=120513"/>
		<updated>2026-06-25T10:24:28Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Disable [[Wikipedia:Keyboard shortcuts|access key]]s&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-confirmationRollback-mobile.js&amp;diff=120511</id>
		<title>MediaWiki:Gadget-confirmationRollback-mobile.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-confirmationRollback-mobile.js&amp;diff=120511"/>
		<updated>2026-06-25T10:24:21Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/********************************************************************&lt;br /&gt;
**                ***WARNING: GLOBAL GADGET FILE***                **&lt;br /&gt;
** Any changes to this file will affect many users. Please discuss **&lt;br /&gt;
**    changes on the talk page or at [[WP:VPT]] before editing.    **&lt;br /&gt;
********************************************************************/&lt;br /&gt;
&lt;br /&gt;
//&amp;lt;nowiki&amp;gt;&lt;br /&gt;
(function() {&lt;br /&gt;
	if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {&lt;br /&gt;
		$(&amp;quot;.mw-rollback-link&amp;quot;).on(&#039;click&#039;, function(e) {&lt;br /&gt;
			var linkText = $(e.target).text(),&lt;br /&gt;
				count = linkText.match(/\d/) ? linkText.match(/\d+/)[0] : null,&lt;br /&gt;
				message = &#039;Rollback &#039; + (count ? count + &#039; edits&#039; : &#039;edit&#039;) + &#039; by &#039; + mw.util.getParamValue(&#039;from&#039;,e.target.href) + &#039;?&#039;;&lt;br /&gt;
			if(!confirm(message)) return e.preventDefault();&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
}());&lt;br /&gt;
//&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-confirmationRollback-mobile&amp;diff=120509</id>
		<title>MediaWiki:Gadget-confirmationRollback-mobile</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-confirmationRollback-mobile&amp;diff=120509"/>
		<updated>2026-06-25T10:24:20Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;sup&amp;gt;&amp;lt;abbr title=&amp;quot;{{int:gadgets-default}}&amp;quot;&amp;gt;(D)&amp;lt;/abbr&amp;gt;&amp;lt;/sup&amp;gt; Require confirmation before performing rollback on mobile devices&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-modrollback.js&amp;diff=120507</id>
		<title>MediaWiki:Gadget-modrollback.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-modrollback.js&amp;diff=120507"/>
		<updated>2026-06-25T10:23:57Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;mw.loader.load( &#039;//www.mediawiki.org/w/index.php?title=MediaWiki:Gadget-modrollback.js&amp;amp;action=raw&amp;amp;ctype=text/javascript&#039; );&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-modrollback&amp;diff=120505</id>
		<title>MediaWiki:Gadget-modrollback</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-modrollback&amp;diff=120505"/>
		<updated>2026-06-25T10:23:56Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;sup&amp;gt;&amp;lt;abbr title=&amp;quot;{{int:gadgets-sister}}&amp;quot;&amp;gt;(S)&amp;lt;/abbr&amp;gt;&amp;lt;/sup&amp;gt; After rolling back a user&#039;s edit, automatically open their contributions page. (Note: Incompatible with the &amp;quot;{{int:Tog-showrollbackconfirmation}}&amp;quot; appearance preference).&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=Module:Gadgets&amp;diff=120503</id>
		<title>Module:Gadgets</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=Module:Gadgets&amp;diff=120503"/>
		<updated>2026-06-24T20:29:38Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local p = {}&lt;br /&gt;
&lt;br /&gt;
p.parse = function()&lt;br /&gt;
	local text = mw.title.new(&#039;MediaWiki:Gadgets-definition&#039;):getContent()&lt;br /&gt;
	local lines = mw.text.split(text, &#039;\n&#039;, false)&lt;br /&gt;
	&lt;br /&gt;
	local repo = {}&lt;br /&gt;
	for _, line in ipairs(lines) do&lt;br /&gt;
		if line:sub(1, 1) == &#039;*&#039; then&lt;br /&gt;
			local name, options, pages = p.parse_line(line)&lt;br /&gt;
			if name and #pages ~= 0 then&lt;br /&gt;
				repo[name] = { options = options, pages = pages }&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return repo&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
p.parse_line = function(def) &lt;br /&gt;
	local pattern = &amp;quot;^%*%s*(.+)%s*(%b[])%s*(.-)$&amp;quot;&lt;br /&gt;
	local name, opts, pageList = string.match(def, pattern)&lt;br /&gt;
	&lt;br /&gt;
	if name then&lt;br /&gt;
		name = mw.text.trim(name)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Process options string into a Lua table&lt;br /&gt;
    local options = {}	&lt;br /&gt;
	if opts then&lt;br /&gt;
	    -- Extracting the options without square brackets and trimming spaces&lt;br /&gt;
	    opts = opts:sub(2, -2):gsub(&amp;quot;%s+&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
	    &lt;br /&gt;
	    for pair in opts:gmatch(&amp;quot;%s*([^|]+)%s*|?&amp;quot;) do&lt;br /&gt;
		    local key, value = pair:match(&amp;quot;%s*([^=]+)%s*=%s*([^=|]+)%s*&amp;quot;)&lt;br /&gt;
		    if key and value then&lt;br /&gt;
		        options[key:match(&amp;quot;%s*(.-)%s*$&amp;quot;)] = value:match(&amp;quot;^%s*(.-)%s*$&amp;quot;)&lt;br /&gt;
		    else&lt;br /&gt;
		        key = pair:match(&amp;quot;%s*(.-)%s*$&amp;quot;)&lt;br /&gt;
		        options[key] = true&lt;br /&gt;
		    end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Process page list into an array&lt;br /&gt;
	local pages = {}&lt;br /&gt;
	if pageList then&lt;br /&gt;
	    for page in pageList:gmatch(&amp;quot;[^|]+&amp;quot;) do&lt;br /&gt;
	        table.insert(pages, mw.text.trim(page))&lt;br /&gt;
	    end&lt;br /&gt;
    end&lt;br /&gt;
    return name, options, pages&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
p.get_type = function(def) &lt;br /&gt;
	if def.options.type == &#039;general&#039; or def.options.type == &#039;styles&#039; then&lt;br /&gt;
		return def.options.type&lt;br /&gt;
	end&lt;br /&gt;
	if def.options.dependencies ~= nil then&lt;br /&gt;
		return &#039;general&#039;&lt;br /&gt;
	end&lt;br /&gt;
	for _, page in ipairs(def.pages) do&lt;br /&gt;
		if not string.match(page, &#039;%.css$&#039;) then&lt;br /&gt;
			return &#039;general&#039;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;styles&#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
p.get_usage = function(name)&lt;br /&gt;
	-- escape name for use in pattern&lt;br /&gt;
	name = name:gsub(&amp;quot;[%-%.%+%[%]%(%)%$%^%%%?%*]&amp;quot;, &amp;quot;%%%1&amp;quot;):gsub(&amp;quot;_&amp;quot;, &amp;quot; &amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	-- rely on [[Project:GUS2Wiki]] until [[phab:T354890]] is implemented&lt;br /&gt;
	local _, _, count = mw.title.new(&#039;Project:GUS2Wiki&#039;):getContent():find(&#039;\n&#039;..name..&#039;,(%d+)&#039;)&lt;br /&gt;
	return tonumber(count) or -1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=Module:Validate_gadgets&amp;diff=120501</id>
		<title>Module:Validate gadgets</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=Module:Validate_gadgets&amp;diff=120501"/>
		<updated>2026-06-24T20:29:38Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local MessageBox = require(&#039;Module:Message box&#039;)&lt;br /&gt;
local Gadgets = require(&#039;Module:Gadgets&#039;)&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
local function arr_contains(array, val)&lt;br /&gt;
    for _, value in ipairs(array) do&lt;br /&gt;
        if value == val then&lt;br /&gt;
            return true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local BOOLEAN_OPTIONS = {&lt;br /&gt;
	&#039;ResourceLoader&#039;, &#039;default&#039;, &#039;package&#039;, &#039;hidden&#039;, &#039;supportsUrlLoad&#039;, &#039;requiresES6&#039;&lt;br /&gt;
}&lt;br /&gt;
local STRING_OPTIONS = {&lt;br /&gt;
	&#039;type&#039;, &#039;dependencies&#039;, &#039;peers&#039;, &#039;namespaces&#039;, &#039;actions&#039;, &lt;br /&gt;
	&#039;contentModels&#039;, &#039;categories&#039;, &#039;targets&#039;, &#039;skins&#039;, &#039;rights&#039;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Lists of valid options for things that aren&#039;t exposed to lua &lt;br /&gt;
-- (unlike namespaces that can be accessed from mw.site.namespaces)&lt;br /&gt;
local VALID_CONTENT_MODELS = {&#039;wikitext&#039;, &#039;javascript&#039;, &#039;css&#039;, &#039;json&#039;, &#039;vue&#039;, &#039;MassMessageListContent&#039;, &#039;Scribunto&#039;, &#039;sanitized-css&#039;, &#039;SecurePoll&#039;}&lt;br /&gt;
local VALID_ACTIONS = {&#039;view&#039;, &#039;edit&#039;, &#039;history&#039;, &#039;info&#039;, &#039;move&#039;, &#039;delete&#039;, &#039;undelete&#039;, &#039;protect&#039;, &#039;block&#039; } -- not exhaustive&lt;br /&gt;
&lt;br /&gt;
p.validate = function ()&lt;br /&gt;
	local text = mw.title.new(&#039;MediaWiki:Gadgets-definition&#039;):getContent()&lt;br /&gt;
	local lines = mw.text.split(text, &#039;\n&#039;, false)&lt;br /&gt;
	&lt;br /&gt;
	local repo = {}&lt;br /&gt;
	local allWarnings = {}	&lt;br /&gt;
	&lt;br /&gt;
	-- A bit of parsing is reimplemented here as [[Module:Gadgets]] doesn&#039;t raise warnings&lt;br /&gt;
	-- for invalid lines&lt;br /&gt;
	for _, line in ipairs(lines) do&lt;br /&gt;
		if line:sub(1, 1) == &#039;*&#039; then&lt;br /&gt;
			local name, options, pages = Gadgets.parse_line(line)&lt;br /&gt;
			if not name or #pages == 0 then&lt;br /&gt;
				table.insert(allWarnings, &#039;* Invalid definition: &#039;..line)&lt;br /&gt;
			else&lt;br /&gt;
				repo[name] = { options = options, pages = pages }&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	for name, conf in pairs(repo) do&lt;br /&gt;
		local warnings = p.create_warnings(name, conf.options, conf.pages, repo)&lt;br /&gt;
		for _, warning in ipairs(warnings) do&lt;br /&gt;
			table.insert(allWarnings, &#039;*&#039;..name..&#039;: &#039;..warning)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if #allWarnings ~= 0 then&lt;br /&gt;
		return MessageBox.main(&#039;ombox&#039;, {&lt;br /&gt;
			text = &#039;&amp;lt;b&amp;gt;Issues in gadget definitions:&amp;lt;/b&amp;gt;\n&#039; .. table.concat(allWarnings, &#039;\n&#039;),&lt;br /&gt;
			type = &#039;delete&#039;,&lt;br /&gt;
			class = &#039;gadgets-validation&#039;&lt;br /&gt;
		})&lt;br /&gt;
	elseif require(&#039;Module:If preview/configuration&#039;).preview then&lt;br /&gt;
		return MessageBox.main(&#039;ombox&#039;, {&lt;br /&gt;
			text = &#039;&amp;lt;b&amp;gt;Issues in gadget definitions:&amp;lt;/b&amp;gt; &amp;lt;i&amp;gt;No issues found!&amp;lt;/i&amp;gt;&#039;,&lt;br /&gt;
			type = &#039;notice&#039;,&lt;br /&gt;
			image = &#039;[[File:Check-green.svg|30px]]&#039;,&lt;br /&gt;
			class = &#039;gadgets-validation&#039;&lt;br /&gt;
		})&lt;br /&gt;
	else &lt;br /&gt;
		return &#039;&#039;&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
p.create_warnings = function(name, options, pages, repo)&lt;br /&gt;
	local warnings = {}&lt;br /&gt;
	&lt;br /&gt;
	-- RL module name (ext.gadget.&amp;lt;name&amp;gt;) should not exceed 255 bytes&lt;br /&gt;
	-- so a limit of 255 - 11 = 244 bytes for gadget name&lt;br /&gt;
	if string.len(name) &amp;gt; 244 then&lt;br /&gt;
		table.insert(warnings, &#039;Gadget name must not exceed 244 bytes&#039;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Per ResourceLoader::isValidModuleName&lt;br /&gt;
	if name:gsub(&#039;[|,!]&#039;, &#039;&#039;) ~= name then&lt;br /&gt;
		table.insert(warnings, &#039;Gadget name must not contain pipes (|), commas (,) or exclamation marks (!)&#039;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Pattern per MediaWikiGadgetDefinitionsRepo::newFromDefinition&lt;br /&gt;
	if not string.match(name, &amp;quot;^[a-zA-Z][-_:%.%w ]*[a-zA-Z0-9]?$&amp;quot;) then&lt;br /&gt;
		table.insert(warnings, &#039;Gadget name is used as part of the name of a form field, and must follow the rules defined in https://www.w3.org/TR/html4/types.html#type-cdata&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Look for invalid options&lt;br /&gt;
	for key, value in pairs(options) do &lt;br /&gt;
		if arr_contains(BOOLEAN_OPTIONS, key) then&lt;br /&gt;
			if value ~= true then &lt;br /&gt;
				table.insert(warnings, &#039;Option &#039;..key..&#039; is a boolean: should have no value&#039;)&lt;br /&gt;
			end &lt;br /&gt;
		elseif arr_contains(STRING_OPTIONS, key) then &lt;br /&gt;
			if value == true then &lt;br /&gt;
				table.insert(warnings, &#039;Option &#039;..key..&#039; must have a value&#039;)&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			table.insert(warnings, &#039;Option &#039;..key..&#039; is unrecognised&#039;)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
    if options.type ~= nil and options.type ~= &#039;general&#039; and options.type ~= &#039;styles&#039; then&lt;br /&gt;
    	table.insert(warnings, &#039;Allowed values for type are: general, styles&#039;)&lt;br /&gt;
    end&lt;br /&gt;
    if options.targets ~= nil then&lt;br /&gt;
    	table.insert(warnings, &#039;Setting targets in gadget defintion is deprecated and no longer has any effect&#039;)&lt;br /&gt;
    end&lt;br /&gt;
    if options.namespaces ~= nil then&lt;br /&gt;
    	for _, id in ipairs(mw.text.split(options.namespaces, &#039;,&#039;, false)) do&lt;br /&gt;
    		if not string.match(id, &#039;^-?%d+$&#039;) then&lt;br /&gt;
    			table.insert(warnings, &#039;Invalid namespace id: &#039;..id..&#039; - must be numeric&#039;)&lt;br /&gt;
    		elseif mw.site.namespaces[tonumber(id)] == nil then&lt;br /&gt;
    			table.insert(warnings, &#039;Namespace id &#039;..id..&#039; is invalid&#039;)&lt;br /&gt;
    		end&lt;br /&gt;
    	end&lt;br /&gt;
    end&lt;br /&gt;
    if options.actions ~= nil then&lt;br /&gt;
    	for _, action in ipairs(mw.text.split(options.actions, &#039;,&#039;, false)) do&lt;br /&gt;
			if not arr_contains(VALID_ACTIONS, action) then&lt;br /&gt;
    			table.insert(warnings, &#039;Action &#039;..action..&#039; is unrecognised&#039;)&lt;br /&gt;
    		end&lt;br /&gt;
    	end&lt;br /&gt;
    end&lt;br /&gt;
    if options.contentModels ~= nil then&lt;br /&gt;
    	for _, model in ipairs(mw.text.split(options.contentModels, &#039;,&#039;, false)) do&lt;br /&gt;
    		if not arr_contains(VALID_CONTENT_MODELS, model) then&lt;br /&gt;
    			table.insert(warnings, &#039;Content model &#039;..model..&#039; is unrecognised&#039;)&lt;br /&gt;
    		end&lt;br /&gt;
    	end&lt;br /&gt;
    end&lt;br /&gt;
    if options.skins ~= nil then&lt;br /&gt;
    	for _, skin in ipairs(mw.text.split(options.skins, &#039;,&#039;, false)) do&lt;br /&gt;
    		if not mw.message.new(&#039;skinname-&#039; .. skin):exists() then&lt;br /&gt;
    			table.insert(warnings, &#039;Skin &#039;..skin..&#039; is not available&#039;)&lt;br /&gt;
    		end&lt;br /&gt;
    	end&lt;br /&gt;
    end&lt;br /&gt;
    if options.rights ~= nil then&lt;br /&gt;
    	for _, right in ipairs(mw.text.split(options.rights, &#039;,&#039;, false)) do&lt;br /&gt;
    		if not mw.message.new(&#039;right-&#039; .. right):exists() then&lt;br /&gt;
    			table.insert(warnings, &#039;User right &#039;..right..&#039; does not exist&#039;)&lt;br /&gt;
    		end&lt;br /&gt;
    	end&lt;br /&gt;
    end&lt;br /&gt;
    -- TODO: check that pages in options.categories exist, but Gadgets.parse_line removes &lt;br /&gt;
	-- whitespaces in options, mangling the category names&lt;br /&gt;
&lt;br /&gt;
    local hasScripts = false&lt;br /&gt;
    local hasJsons = false&lt;br /&gt;
    local hasVues = false&lt;br /&gt;
    for _, page in ipairs(pages) do&lt;br /&gt;
    	page = &#039;MediaWiki:Gadget-&#039; .. page&lt;br /&gt;
    	local title = mw.title.new(page)&lt;br /&gt;
    	if title == nil or not title.exists then&lt;br /&gt;
    		table.insert(warnings, &#039;Page [[&#039;..page..&#039;]] does not exist&#039;)&lt;br /&gt;
    	else &lt;br /&gt;
	    	local ext = title.text:match(&amp;quot;%.([^%.]+)$&amp;quot;)&lt;br /&gt;
	    	if ext == &#039;js&#039; then&lt;br /&gt;
	    		if title.contentModel ~= &#039;javascript&#039; then&lt;br /&gt;
	    			table.insert(warnings, &#039;Page [[&#039;..page..&#039;]] is not of JavaScript content model&#039;)&lt;br /&gt;
	    		else&lt;br /&gt;
	    			hasScripts = true&lt;br /&gt;
	    		end&lt;br /&gt;
	    	elseif ext == &#039;css&#039; then&lt;br /&gt;
	    		if title.contentModel ~= &#039;css&#039; then&lt;br /&gt;
	    			table.insert(warnings, &#039;Page [[&#039;..page..&#039;]] is not of CSS content model&#039;)&lt;br /&gt;
	    		end&lt;br /&gt;
	    	elseif ext == &#039;json&#039; then&lt;br /&gt;
	    		if title.contentModel ~= &#039;json&#039; then&lt;br /&gt;
	    			table.insert(warnings, &#039;Page [[&#039;..page..&#039;]] is not of JSON content model&#039;)&lt;br /&gt;
	    		else&lt;br /&gt;
	    			hasJsons = true&lt;br /&gt;
	    		end&lt;br /&gt;
	    	elseif ext == &#039;vue&#039; then&lt;br /&gt;
	    		if title.contentModel ~= &#039;vue&#039; then&lt;br /&gt;
	    			table.insert(warnings, &#039;Page [[&#039;..page..&#039;]] is not of Vue content model&#039;)&lt;br /&gt;
	    		else&lt;br /&gt;
	    			hasVues = true&lt;br /&gt;
	    		end&lt;br /&gt;
	    	else&lt;br /&gt;
	    		table.insert(warnings, &#039;Page [[&#039;..page..&#039;]] is not JS/CSS/JSON/Vue, will be ignored&#039;)&lt;br /&gt;
	    	end&lt;br /&gt;
	    end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if not options.hidden then&lt;br /&gt;
	    local description_page = mw.title.new(&#039;MediaWiki:Gadget-&#039;..name)&lt;br /&gt;
	    if description_page == nil or not description_page.exists then&lt;br /&gt;
	    	table.insert(warnings, &#039;Description [[&#039;..description_page.fullText..&#039;]] for use in Special:Preferences does not exist&#039;)&lt;br /&gt;
	    end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
    if options.package == nil and hasJsons then&lt;br /&gt;
    	table.insert(warnings, &#039;JSON pages cannot be used in non-package gadgets&#039;)&lt;br /&gt;
    end&lt;br /&gt;
	if options.package == nil and hasVues then &lt;br /&gt;
		table.insert(warnings, &#039;Vue pages cannot be used in non-package gadgets&#039;)&lt;br /&gt;
    end&lt;br /&gt;
    if options.requiresES6 ~= nil and options.default ~= nil then&lt;br /&gt;
    	table.insert(warnings, &#039;Default gadget cannot use requiresES6 flag&#039;)&lt;br /&gt;
    end&lt;br /&gt;
    if options.type == &#039;styles&#039; and hasScripts then&lt;br /&gt;
    	table.insert(warnings, &#039;JS pages will be ignored as gadget sets type=styles&#039;)&lt;br /&gt;
    end&lt;br /&gt;
    if options.type == &#039;styles&#039; and options.peers ~= nil then&lt;br /&gt;
    	table.insert(warnings, &#039;Styles-only gadget cannot have peers&#039;)&lt;br /&gt;
    end&lt;br /&gt;
    if options.type == &#039;styles&#039; and options.dependencies ~= nil then&lt;br /&gt;
    	table.insert(warnings, &#039;Styles-only gadget cannot have dependencies&#039;)&lt;br /&gt;
    end&lt;br /&gt;
    if options.package ~= nil and not hasScripts then&lt;br /&gt;
    	table.insert(warnings, &#039;Package gadget must have at least one JS page&#039;)&lt;br /&gt;
    end&lt;br /&gt;
    if options.ResourceLoader == nil and hasScripts then&lt;br /&gt;
    	table.insert(warnings, &#039;ResourceLoader option must be set&#039;)&lt;br /&gt;
    end&lt;br /&gt;
    -- Causes warnings on styles-only gadgets using skins param &lt;br /&gt;
    -- if options.hidden ~= nil and (options.namespaces ~= nil or options.actions ~= nil or options.rights ~= nil or options.contentModels ~= nil or options.skins ~= nil) then&lt;br /&gt;
    -- 	table.insert(warnings, &#039;Conditional load options are not applicable for hidden gadget&#039;)&lt;br /&gt;
    -- end&lt;br /&gt;
&lt;br /&gt;
	if options.peers ~= nil then&lt;br /&gt;
		for _, peer in ipairs(mw.text.split(options.peers, &#039;,&#039;, false)) do &lt;br /&gt;
			if repo[peer] == nil then&lt;br /&gt;
				table.insert(warnings, &#039;Peer gadget &#039;..peer..&#039; is not defined&#039;)&lt;br /&gt;
			elseif Gadgets.get_type(repo[peer]) == &#039;general&#039; then&lt;br /&gt;
				table.insert(warnings, &#039;Peer gadget &#039;..peer..&#039; must be styles-only gadget&#039;)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if options.dependencies ~= nil then&lt;br /&gt;
		for _, dep in ipairs(mw.text.split(options.dependencies, &#039;,&#039;, false)) do&lt;br /&gt;
			if dep:sub(1, 11) == &#039;ext.gadget.&#039; then&lt;br /&gt;
				local dep_gadget = dep:sub(12)&lt;br /&gt;
				if repo[dep_gadget] == nil then&lt;br /&gt;
					table.insert(warnings, &#039;Dependency gadget &#039;..dep_gadget..&#039; is not defined&#039;)&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return warnings&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=Module:If_preview/styles.css&amp;diff=120499</id>
		<title>Module:If preview/styles.css</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=Module:If_preview/styles.css&amp;diff=120499"/>
		<updated>2026-06-24T20:29:38Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* {{pp|small=yes}} */&lt;br /&gt;
.preview-warning {&lt;br /&gt;
	font-style: italic;&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	padding-left: 1.6em;&lt;br /&gt;
	margin-bottom: 0.5em;&lt;br /&gt;
	color: var(--color-error, red);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* The templatestyles causes an &#039;empty&#039; span between hatnotes */&lt;br /&gt;
.preview-warning + span.mw-empty-elt + .preview-warning,&lt;br /&gt;
/* remove this selector when Parsoid is the only parser, see also [[phab:T200206]] */&lt;br /&gt;
.preview-warning + link + .preview-warning {&lt;br /&gt;
	margin-top: -0.5em;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=Module:If_preview/configuration&amp;diff=120497</id>
		<title>Module:If preview/configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=Module:If_preview/configuration&amp;diff=120497"/>
		<updated>2026-06-24T20:29:38Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--[[&lt;br /&gt;
We perform the actual check for whether this is a preview here since&lt;br /&gt;
preprocessing is relatively expensive.&lt;br /&gt;
]]&lt;br /&gt;
local frame = mw.getCurrentFrame()&lt;br /&gt;
&lt;br /&gt;
local function is_preview()&lt;br /&gt;
	local revision_id = frame:preprocess(&#039;{{REVISIONID}}&#039;)&lt;br /&gt;
	-- {{REVISIONID}} is usually the empty string when previewed.&lt;br /&gt;
	-- I don&#039;t know why we&#039;re checking for nil but hey, maybe someday things&lt;br /&gt;
	-- would have broken&lt;br /&gt;
	return revision_id == nil or revision_id == &#039;&#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function templatestyles()&lt;br /&gt;
	return frame:extensionTag{&lt;br /&gt;
		name = &#039;templatestyles&#039;, args = { src = &#039;Module:If preview/styles.css&#039; }&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
	preview = is_preview(),&lt;br /&gt;
	templatestyles = templatestyles(),&lt;br /&gt;
	warning_infrastructure = &#039;%s&amp;lt;div class=&amp;quot;preview-warning&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Preview warning:&amp;lt;/strong&amp;gt; %s&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
	missing_warning = &#039;The template has no warning text. Please add a warning.&#039;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=Module:Message_box&amp;diff=120495</id>
		<title>Module:Message box</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=Module:Message_box&amp;diff=120495"/>
		<updated>2026-06-24T20:29:38Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;require(&#039;strict&#039;)&lt;br /&gt;
local getArgs&lt;br /&gt;
local yesno = require(&#039;Module:Yesno&#039;)&lt;br /&gt;
local lang = mw.language.getContentLanguage()&lt;br /&gt;
&lt;br /&gt;
local CONFIG_MODULE = &#039;Module:Message box/configuration&#039;&lt;br /&gt;
local DEMOSPACES = {talk = &#039;tmbox&#039;, image = &#039;imbox&#039;, file = &#039;imbox&#039;, category = &#039;cmbox&#039;, article = &#039;ambox&#039;, main = &#039;ambox&#039;}&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Helper functions&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function getTitleObject(...)&lt;br /&gt;
	-- Get the title object, passing the function through pcall&lt;br /&gt;
	-- in case we are over the expensive function count limit.&lt;br /&gt;
	local success, title = pcall(mw.title.new, ...)&lt;br /&gt;
	if success then&lt;br /&gt;
		return title&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function union(t1, t2)&lt;br /&gt;
	-- Returns the union of two arrays.&lt;br /&gt;
	local vals = {}&lt;br /&gt;
	for i, v in ipairs(t1) do&lt;br /&gt;
		vals[v] = true&lt;br /&gt;
	end&lt;br /&gt;
	for i, v in ipairs(t2) do&lt;br /&gt;
		vals[v] = true&lt;br /&gt;
	end&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for k in pairs(vals) do&lt;br /&gt;
		table.insert(ret, k)&lt;br /&gt;
	end&lt;br /&gt;
	table.sort(ret)&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getArgNums(args, prefix)&lt;br /&gt;
	local nums = {}&lt;br /&gt;
	for k, v in pairs(args) do&lt;br /&gt;
		local num = mw.ustring.match(tostring(k), &#039;^&#039; .. prefix .. &#039;([1-9]%d*)$&#039;)&lt;br /&gt;
		if num then&lt;br /&gt;
			table.insert(nums, tonumber(num))&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	table.sort(nums)&lt;br /&gt;
	return nums&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Box class definition&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local MessageBox = {}&lt;br /&gt;
MessageBox.__index = MessageBox&lt;br /&gt;
&lt;br /&gt;
function MessageBox.new(boxType, args, cfg)&lt;br /&gt;
	args = args or {}&lt;br /&gt;
	local obj = {}&lt;br /&gt;
&lt;br /&gt;
	-- Set the title object and the namespace.&lt;br /&gt;
	obj.title = getTitleObject(args.page) or mw.title.getCurrentTitle()&lt;br /&gt;
&lt;br /&gt;
	-- Set the config for our box type.&lt;br /&gt;
	obj.cfg = cfg[boxType]&lt;br /&gt;
	if not obj.cfg then&lt;br /&gt;
		local ns = obj.title.namespace&lt;br /&gt;
		-- boxType is &amp;quot;mbox&amp;quot; or invalid input&lt;br /&gt;
		if args.demospace and args.demospace ~= &#039;&#039; then&lt;br /&gt;
			-- implement demospace parameter of mbox&lt;br /&gt;
			local demospace = string.lower(args.demospace)&lt;br /&gt;
			if DEMOSPACES[demospace] then&lt;br /&gt;
				-- use template from DEMOSPACES&lt;br /&gt;
				obj.cfg = cfg[DEMOSPACES[demospace]]&lt;br /&gt;
			elseif string.find( demospace, &#039;talk&#039; ) then&lt;br /&gt;
				-- demo as a talk page&lt;br /&gt;
				obj.cfg = cfg.tmbox&lt;br /&gt;
			else&lt;br /&gt;
				-- default to ombox&lt;br /&gt;
				obj.cfg = cfg.ombox&lt;br /&gt;
			end&lt;br /&gt;
		elseif ns == 0 then&lt;br /&gt;
			obj.cfg = cfg.ambox -- main namespace&lt;br /&gt;
		elseif ns == 6 then&lt;br /&gt;
			obj.cfg = cfg.imbox -- file namespace&lt;br /&gt;
		elseif ns == 14 then&lt;br /&gt;
			obj.cfg = cfg.cmbox -- category namespace&lt;br /&gt;
		else&lt;br /&gt;
			local nsTable = mw.site.namespaces[ns]&lt;br /&gt;
			if nsTable and nsTable.isTalk then&lt;br /&gt;
				obj.cfg = cfg.tmbox -- any talk namespace&lt;br /&gt;
			else&lt;br /&gt;
				obj.cfg = cfg.ombox -- other namespaces or invalid input&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Set the arguments, and remove all blank arguments except for the ones&lt;br /&gt;
	-- listed in cfg.allowBlankParams.&lt;br /&gt;
	do&lt;br /&gt;
		local newArgs = {}&lt;br /&gt;
		for k, v in pairs(args) do&lt;br /&gt;
			if v ~= &#039;&#039; then&lt;br /&gt;
				newArgs[k] = v&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		for i, param in ipairs(obj.cfg.allowBlankParams or {}) do&lt;br /&gt;
			newArgs[param] = args[param]&lt;br /&gt;
		end&lt;br /&gt;
		obj.args = newArgs&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Define internal data structure.&lt;br /&gt;
	obj.categories = {}&lt;br /&gt;
	obj.classes = {}&lt;br /&gt;
	-- For lazy loading of [[Module:Category handler]].&lt;br /&gt;
	obj.hasCategories = false&lt;br /&gt;
&lt;br /&gt;
	return setmetatable(obj, MessageBox)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function MessageBox:addCat(ns, cat, sort)&lt;br /&gt;
	if not cat then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	if sort then&lt;br /&gt;
		cat = string.format(&#039;[[Category:%s|%s]]&#039;, cat, sort)&lt;br /&gt;
	else&lt;br /&gt;
		cat = string.format(&#039;[[Category:%s]]&#039;, cat)&lt;br /&gt;
	end&lt;br /&gt;
	self.hasCategories = true&lt;br /&gt;
	self.categories[ns] = self.categories[ns] or {}&lt;br /&gt;
	table.insert(self.categories[ns], cat)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function MessageBox:addClass(class)&lt;br /&gt;
	if not class then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	table.insert(self.classes, class)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function MessageBox:setParameters()&lt;br /&gt;
	local args = self.args&lt;br /&gt;
	local cfg = self.cfg&lt;br /&gt;
&lt;br /&gt;
	-- Get type data.&lt;br /&gt;
	self.type = args.type&lt;br /&gt;
	local typeData = cfg.types[self.type]&lt;br /&gt;
	self.invalidTypeError = cfg.showInvalidTypeError&lt;br /&gt;
		and self.type&lt;br /&gt;
		and not typeData&lt;br /&gt;
	typeData = typeData or cfg.types[cfg.default]&lt;br /&gt;
	self.typeClass = typeData.class&lt;br /&gt;
	self.typeImage = typeData.image&lt;br /&gt;
	self.typeImageNeedsLink = typeData.imageNeedsLink&lt;br /&gt;
&lt;br /&gt;
	-- Find if the box has been wrongly substituted.&lt;br /&gt;
	self.isSubstituted = cfg.substCheck and args.subst == &#039;SUBST&#039;&lt;br /&gt;
&lt;br /&gt;
	-- Find whether we are using a small message box.&lt;br /&gt;
	self.isSmall = cfg.allowSmall and (&lt;br /&gt;
		cfg.smallParam and args.small == cfg.smallParam&lt;br /&gt;
		or not cfg.smallParam and yesno(args.small)&lt;br /&gt;
	)&lt;br /&gt;
&lt;br /&gt;
	-- Set the below row.&lt;br /&gt;
	self.below = cfg.below and args.below&lt;br /&gt;
	&lt;br /&gt;
	-- Add attributes, classes and styles.&lt;br /&gt;
	self.id = args.id&lt;br /&gt;
	self.name = args.name&lt;br /&gt;
	if self.name then&lt;br /&gt;
		self:addClass(&#039;box-&#039; .. string.gsub(self.name,&#039; &#039;,&#039;_&#039;))&lt;br /&gt;
	end&lt;br /&gt;
	if yesno(args.plainlinks) ~= false then&lt;br /&gt;
		self:addClass(&#039;plainlinks&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	if self.below then&lt;br /&gt;
		self:addClass(&#039;mbox-with-below&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	for _, class in ipairs(cfg.classes or {}) do&lt;br /&gt;
		self:addClass(class)&lt;br /&gt;
	end&lt;br /&gt;
	if self.isSmall then&lt;br /&gt;
		self:addClass(cfg.smallClass or &#039;mbox-small&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	self:addClass(self.typeClass)&lt;br /&gt;
	self:addClass(args.class)&lt;br /&gt;
	self.style = args.style&lt;br /&gt;
	self.attrs = args.attrs&lt;br /&gt;
&lt;br /&gt;
	-- Set text style.&lt;br /&gt;
	self.textstyle = args.textstyle&lt;br /&gt;
&lt;br /&gt;
	-- Set image classes.&lt;br /&gt;
	self.imageRightClass = args.imagerightclass or args.imageclass&lt;br /&gt;
	self.imageLeftClass = args.imageleftclass or args.imageclass&lt;br /&gt;
&lt;br /&gt;
	-- Find if we are on the template page or not. This functionality is only&lt;br /&gt;
	-- used if useCollapsibleTextFields is set, or if both cfg.templateCategory&lt;br /&gt;
	-- and cfg.templateCategoryRequireName are set.&lt;br /&gt;
	self.useCollapsibleTextFields = cfg.useCollapsibleTextFields&lt;br /&gt;
	if self.useCollapsibleTextFields&lt;br /&gt;
		or cfg.templateCategory&lt;br /&gt;
		and cfg.templateCategoryRequireName&lt;br /&gt;
	then&lt;br /&gt;
		if self.name then&lt;br /&gt;
			local templateName = mw.ustring.match(&lt;br /&gt;
				self.name,&lt;br /&gt;
				&#039;^[tT][eE][mM][pP][lL][aA][tT][eE][%s_]*:[%s_]*(.*)$&#039;&lt;br /&gt;
			) or self.name&lt;br /&gt;
			templateName = &#039;Template:&#039; .. templateName&lt;br /&gt;
			self.templateTitle = getTitleObject(templateName)&lt;br /&gt;
		end&lt;br /&gt;
		self.isTemplatePage = self.templateTitle&lt;br /&gt;
			and mw.title.equals(self.title, self.templateTitle)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Process data for collapsible text fields. At the moment these are only&lt;br /&gt;
	-- used in {{ambox}}.&lt;br /&gt;
	if self.useCollapsibleTextFields then&lt;br /&gt;
		-- Get the self.issue value.&lt;br /&gt;
		if self.isSmall and args.smalltext then&lt;br /&gt;
			self.issue = args.smalltext&lt;br /&gt;
		else&lt;br /&gt;
			local sect&lt;br /&gt;
			if args.sect == &#039;&#039; then&lt;br /&gt;
				sect = &#039;This &#039; .. (cfg.sectionDefault or &#039;page&#039;)&lt;br /&gt;
			elseif type(args.sect) == &#039;string&#039; then&lt;br /&gt;
				sect = &#039;This &#039; .. args.sect&lt;br /&gt;
			end&lt;br /&gt;
			local issue = args.issue&lt;br /&gt;
			issue = type(issue) == &#039;string&#039; and issue ~= &#039;&#039; and issue or nil&lt;br /&gt;
			local text = args.text&lt;br /&gt;
			text = type(text) == &#039;string&#039; and text or nil&lt;br /&gt;
			local issues = {}&lt;br /&gt;
			table.insert(issues, sect)&lt;br /&gt;
			table.insert(issues, issue)&lt;br /&gt;
			table.insert(issues, text)&lt;br /&gt;
			self.issue = table.concat(issues, &#039; &#039;)&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		-- Get the self.talk value.&lt;br /&gt;
		local talk = args.talk&lt;br /&gt;
		-- Show talk links on the template page or template subpages if the talk&lt;br /&gt;
		-- parameter is blank.&lt;br /&gt;
		if talk == &#039;&#039;&lt;br /&gt;
			and self.templateTitle&lt;br /&gt;
			and (&lt;br /&gt;
				mw.title.equals(self.templateTitle, self.title)&lt;br /&gt;
				or self.title:isSubpageOf(self.templateTitle)&lt;br /&gt;
			)&lt;br /&gt;
		then&lt;br /&gt;
			talk = &#039;#&#039;&lt;br /&gt;
		elseif talk == &#039;&#039; then&lt;br /&gt;
			talk = nil&lt;br /&gt;
		end&lt;br /&gt;
		if talk then&lt;br /&gt;
			-- If the talk value is a talk page, make a link to that page. Else&lt;br /&gt;
			-- assume that it&#039;s a section heading, and make a link to the talk&lt;br /&gt;
			-- page of the current page with that section heading.&lt;br /&gt;
			local talkTitle = getTitleObject(talk)&lt;br /&gt;
			local talkArgIsTalkPage = true&lt;br /&gt;
			if not talkTitle or not talkTitle.isTalkPage then&lt;br /&gt;
				talkArgIsTalkPage = false&lt;br /&gt;
				talkTitle = getTitleObject(&lt;br /&gt;
					self.title.text,&lt;br /&gt;
					mw.site.namespaces[self.title.namespace].talk.id&lt;br /&gt;
				)&lt;br /&gt;
			end&lt;br /&gt;
			if talkTitle and talkTitle.exists then&lt;br /&gt;
                local talkText&lt;br /&gt;
                if self.isSmall then&lt;br /&gt;
                    local talkLink = talkArgIsTalkPage and talk or (talkTitle.prefixedText .. (talk == &#039;#&#039; and &#039;&#039; or &#039;#&#039;) .. talk)&lt;br /&gt;
                    talkText = string.format(&#039;([[%s|talk]])&#039;, talkLink)&lt;br /&gt;
                else&lt;br /&gt;
                    talkText = &#039;Relevant discussion may be found on&#039;&lt;br /&gt;
                    if talkArgIsTalkPage then&lt;br /&gt;
                        talkText = string.format(&lt;br /&gt;
                            &#039;%s [[%s|%s]].&#039;,&lt;br /&gt;
                            talkText,&lt;br /&gt;
                            talk,&lt;br /&gt;
                            talkTitle.prefixedText&lt;br /&gt;
                        )&lt;br /&gt;
                    else&lt;br /&gt;
                        talkText = string.format(&lt;br /&gt;
                            &#039;%s the [[%s&#039; .. (talk == &#039;#&#039; and &#039;&#039; or &#039;#&#039;) .. &#039;%s|talk page]].&#039;,&lt;br /&gt;
                            talkText,&lt;br /&gt;
                            talkTitle.prefixedText,&lt;br /&gt;
                            talk&lt;br /&gt;
                        )&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
				self.talk = talkText&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		-- Get other values.&lt;br /&gt;
		self.fix = args.fix ~= &#039;&#039; and args.fix or nil&lt;br /&gt;
		local date&lt;br /&gt;
		if args.date and args.date ~= &#039;&#039; then&lt;br /&gt;
			date = args.date&lt;br /&gt;
		elseif args.date == &#039;&#039; and self.isTemplatePage then&lt;br /&gt;
			date = lang:formatDate(&#039;F Y&#039;)&lt;br /&gt;
		end&lt;br /&gt;
		if date then&lt;br /&gt;
			self.date = string.format(&amp;quot; &amp;lt;span class=&#039;date-container&#039;&amp;gt;&amp;lt;i&amp;gt;(&amp;lt;span class=&#039;date&#039;&amp;gt;%s&amp;lt;/span&amp;gt;)&amp;lt;/i&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;, date)&lt;br /&gt;
		end&lt;br /&gt;
		self.info = args.info&lt;br /&gt;
		if yesno(args.removalnotice) then&lt;br /&gt;
			self.removalNotice = cfg.removalNotice&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Set the non-collapsible text field. At the moment this is used by all box&lt;br /&gt;
	-- types other than ambox, and also by ambox when small=yes.&lt;br /&gt;
	if self.isSmall then&lt;br /&gt;
		self.text = args.smalltext or args.text&lt;br /&gt;
	else&lt;br /&gt;
		self.text = args.text&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- General image settings.&lt;br /&gt;
	self.imageCellDiv = not self.isSmall and cfg.imageCellDiv&lt;br /&gt;
	self.imageEmptyCell = cfg.imageEmptyCell&lt;br /&gt;
&lt;br /&gt;
	-- Left image settings.&lt;br /&gt;
	local imageLeft = self.isSmall and args.smallimage or args.image&lt;br /&gt;
	if cfg.imageCheckBlank and imageLeft ~= &#039;blank&#039; and imageLeft ~= &#039;none&#039;&lt;br /&gt;
		or not cfg.imageCheckBlank and imageLeft ~= &#039;none&#039;&lt;br /&gt;
	then&lt;br /&gt;
		self.imageLeft = imageLeft&lt;br /&gt;
		if not imageLeft then&lt;br /&gt;
			local imageSize = self.isSmall&lt;br /&gt;
				and (cfg.imageSmallSize or &#039;30x30px&#039;)&lt;br /&gt;
				or &#039;40x40px&#039;&lt;br /&gt;
			self.imageLeft = string.format(&#039;[[File:%s|%s%s|alt=]]&#039;, self.typeImage&lt;br /&gt;
				or &#039;Information icon4.svg&#039;, imageSize, self.typeImageNeedsLink and &amp;quot;&amp;quot; or &amp;quot;|link=&amp;quot; )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Right image settings.&lt;br /&gt;
	local imageRight = self.isSmall and args.smallimageright or args.imageright&lt;br /&gt;
	if not (cfg.imageRightNone and imageRight == &#039;none&#039;) then&lt;br /&gt;
		self.imageRight = imageRight&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- set templatestyles&lt;br /&gt;
	self.base_templatestyles = cfg.templatestyles&lt;br /&gt;
	self.templatestyles = args.templatestyles&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function MessageBox:setMainspaceCategories()&lt;br /&gt;
	local args = self.args&lt;br /&gt;
	local cfg = self.cfg&lt;br /&gt;
&lt;br /&gt;
	if not cfg.allowMainspaceCategories then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local nums = {}&lt;br /&gt;
	for _, prefix in ipairs{&#039;cat&#039;, &#039;category&#039;, &#039;all&#039;} do&lt;br /&gt;
		args[prefix .. &#039;1&#039;] = args[prefix]&lt;br /&gt;
		nums = union(nums, getArgNums(args, prefix))&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- The following is roughly equivalent to the old {{Ambox/category}}.&lt;br /&gt;
	local date = args.date&lt;br /&gt;
	date = type(date) == &#039;string&#039; and date&lt;br /&gt;
	local preposition = &#039;from&#039;&lt;br /&gt;
	for _, num in ipairs(nums) do&lt;br /&gt;
		local mainCat = args[&#039;cat&#039; .. tostring(num)]&lt;br /&gt;
			or args[&#039;category&#039; .. tostring(num)]&lt;br /&gt;
		local allCat = args[&#039;all&#039; .. tostring(num)]&lt;br /&gt;
		mainCat = type(mainCat) == &#039;string&#039; and mainCat&lt;br /&gt;
		allCat = type(allCat) == &#039;string&#039; and allCat&lt;br /&gt;
		if mainCat and date and date ~= &#039;&#039; then&lt;br /&gt;
			local catTitle = string.format(&#039;%s %s %s&#039;, mainCat, preposition, date)&lt;br /&gt;
			self:addCat(0, catTitle)&lt;br /&gt;
			catTitle = getTitleObject(&#039;Category:&#039; .. catTitle)&lt;br /&gt;
			if not catTitle or not catTitle.exists then&lt;br /&gt;
				self:addCat(0, &#039;Articles with invalid date parameter in template&#039;)&lt;br /&gt;
			end&lt;br /&gt;
		elseif mainCat and (not date or date == &#039;&#039;) then&lt;br /&gt;
			self:addCat(0, mainCat)&lt;br /&gt;
		end&lt;br /&gt;
		if allCat then&lt;br /&gt;
			self:addCat(0, allCat)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function MessageBox:setTemplateCategories()&lt;br /&gt;
	local args = self.args&lt;br /&gt;
	local cfg = self.cfg&lt;br /&gt;
&lt;br /&gt;
	-- Add template categories.&lt;br /&gt;
	if cfg.templateCategory then&lt;br /&gt;
		if cfg.templateCategoryRequireName then&lt;br /&gt;
			if self.isTemplatePage then&lt;br /&gt;
				self:addCat(10, cfg.templateCategory)&lt;br /&gt;
			end&lt;br /&gt;
		elseif not self.title.isSubpage then&lt;br /&gt;
			self:addCat(10, cfg.templateCategory)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Add template error categories.&lt;br /&gt;
	if cfg.templateErrorCategory then&lt;br /&gt;
		local templateErrorCategory = cfg.templateErrorCategory&lt;br /&gt;
		local templateCat, templateSort&lt;br /&gt;
		if not self.name and not self.title.isSubpage then&lt;br /&gt;
			templateCat = templateErrorCategory&lt;br /&gt;
		elseif self.isTemplatePage then&lt;br /&gt;
			local paramsToCheck = cfg.templateErrorParamsToCheck or {}&lt;br /&gt;
			local count = 0&lt;br /&gt;
			for i, param in ipairs(paramsToCheck) do&lt;br /&gt;
				if not args[param] then&lt;br /&gt;
					count = count + 1&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			if count &amp;gt; 0 then&lt;br /&gt;
				templateCat = templateErrorCategory&lt;br /&gt;
				templateSort = tostring(count)&lt;br /&gt;
			end&lt;br /&gt;
			if self.categoryNums and #self.categoryNums &amp;gt; 0 then&lt;br /&gt;
				templateCat = templateErrorCategory&lt;br /&gt;
				templateSort = &#039;C&#039;&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		self:addCat(10, templateCat, templateSort)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function MessageBox:setAllNamespaceCategories()&lt;br /&gt;
	-- Set categories for all namespaces.&lt;br /&gt;
	if self.invalidTypeError then&lt;br /&gt;
		local allSort = (self.title.namespace == 0 and &#039;Main:&#039; or &#039;&#039;) .. self.title.prefixedText&lt;br /&gt;
		self:addCat(&#039;all&#039;, &#039;Wikipedia message box parameter needs fixing&#039;, allSort)&lt;br /&gt;
	end&lt;br /&gt;
	if self.isSubstituted then&lt;br /&gt;
		self:addCat(&#039;all&#039;, &#039;Pages with incorrectly substituted templates&#039;)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function MessageBox:setCategories()&lt;br /&gt;
	if self.title.namespace == 0 then&lt;br /&gt;
		self:setMainspaceCategories()&lt;br /&gt;
	elseif self.title.namespace == 10 then&lt;br /&gt;
		self:setTemplateCategories()&lt;br /&gt;
	end&lt;br /&gt;
	self:setAllNamespaceCategories()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function MessageBox:renderCategories()&lt;br /&gt;
	if not self.hasCategories then&lt;br /&gt;
		-- No categories added, no need to pass them to Category handler so,&lt;br /&gt;
		-- if it was invoked, it would return the empty string.&lt;br /&gt;
		-- So we shortcut and return the empty string.&lt;br /&gt;
		return &amp;quot;&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	-- Convert category tables to strings and pass them through&lt;br /&gt;
	-- [[Module:Category handler]].&lt;br /&gt;
	return require(&#039;Module:Category handler&#039;)._main{&lt;br /&gt;
		main = table.concat(self.categories[0] or {}),&lt;br /&gt;
		template = table.concat(self.categories[10] or {}),&lt;br /&gt;
		all = table.concat(self.categories.all or {}),&lt;br /&gt;
		nocat = self.args.nocat,&lt;br /&gt;
		page = self.args.page&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function MessageBox:exportDiv()&lt;br /&gt;
	local root = mw.html.create()&lt;br /&gt;
&lt;br /&gt;
	-- Add the subst check error.&lt;br /&gt;
	if self.isSubstituted and self.name then&lt;br /&gt;
		root:tag(&#039;b&#039;)&lt;br /&gt;
			:addClass(&#039;error&#039;)&lt;br /&gt;
			:wikitext(string.format(&lt;br /&gt;
				&#039;Template &amp;lt;code&amp;gt;%s[[Template:%s|%s]]%s&amp;lt;/code&amp;gt; has been incorrectly substituted.&#039;,&lt;br /&gt;
				mw.text.nowiki(&#039;{{&#039;), self.name, self.name, mw.text.nowiki(&#039;}}&#039;)&lt;br /&gt;
			))&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local frame = mw.getCurrentFrame()&lt;br /&gt;
	root:wikitext(frame:extensionTag{&lt;br /&gt;
		name = &#039;templatestyles&#039;,&lt;br /&gt;
		args = { src = self.base_templatestyles },&lt;br /&gt;
	})&lt;br /&gt;
	-- Add support for a single custom templatestyles sheet. Undocumented as&lt;br /&gt;
	-- need should be limited and many templates using mbox are substed; we&lt;br /&gt;
	-- don&#039;t want to spread templatestyles sheets around to arbitrary places&lt;br /&gt;
	if self.templatestyles then&lt;br /&gt;
		root:wikitext(frame:extensionTag{&lt;br /&gt;
			name = &#039;templatestyles&#039;,&lt;br /&gt;
			args = { src = self.templatestyles },&lt;br /&gt;
		})&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Create the box.&lt;br /&gt;
	local mbox = root:tag(&#039;div&#039;)&lt;br /&gt;
	mbox:attr(&#039;id&#039;, self.id or nil)&lt;br /&gt;
	for i, class in ipairs(self.classes or {}) do&lt;br /&gt;
		mbox:addClass(class or nil)&lt;br /&gt;
	end&lt;br /&gt;
	mbox&lt;br /&gt;
		:cssText(self.style or nil)&lt;br /&gt;
&lt;br /&gt;
	if self.attrs then&lt;br /&gt;
		mbox:attr(self.attrs)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local flex_container&lt;br /&gt;
	if self.below then&lt;br /&gt;
		-- we need to wrap the flex components (`image(right)` and `text`) in their&lt;br /&gt;
		-- own container div to support the `below` parameter&lt;br /&gt;
		flex_container = mw.html.create(&#039;div&#039;)&lt;br /&gt;
		flex_container:addClass(&#039;mbox-flex&#039;)&lt;br /&gt;
	else&lt;br /&gt;
		-- the mbox itself is the parent, so we need no HTML flex_container&lt;br /&gt;
		flex_container = mw.html.create()&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Add the left-hand image.&lt;br /&gt;
	if self.imageLeft then&lt;br /&gt;
		local imageLeftCell = flex_container:tag(&#039;div&#039;):addClass(&#039;mbox-image&#039;)&lt;br /&gt;
		imageLeftCell&lt;br /&gt;
			:addClass(self.imageLeftClass)&lt;br /&gt;
			:wikitext(self.imageLeft or nil)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Add the text.&lt;br /&gt;
	local textCell = flex_container:tag(&#039;div&#039;):addClass(&#039;mbox-text&#039;)&lt;br /&gt;
	if self.useCollapsibleTextFields then&lt;br /&gt;
		-- The message box uses advanced text parameters that allow things to be&lt;br /&gt;
		-- collapsible. At the moment, only ambox uses this.&lt;br /&gt;
		textCell:cssText(self.textstyle or nil)&lt;br /&gt;
		local textCellDiv = textCell:tag(&#039;div&#039;)&lt;br /&gt;
		textCellDiv&lt;br /&gt;
			:addClass(&#039;mbox-text-span&#039;)&lt;br /&gt;
			:wikitext(self.issue or nil)&lt;br /&gt;
		if (self.talk or self.fix) then&lt;br /&gt;
			textCellDiv:tag(&#039;span&#039;)&lt;br /&gt;
				:addClass(&#039;hide-when-compact&#039;)&lt;br /&gt;
				:wikitext(self.talk and (&#039; &#039; .. self.talk) or nil)&lt;br /&gt;
				:wikitext(self.fix and (&#039; &#039; .. self.fix) or nil)&lt;br /&gt;
		end&lt;br /&gt;
		textCellDiv:wikitext(self.date and (&#039; &#039; .. self.date) or nil)&lt;br /&gt;
		if self.info and not self.isSmall then&lt;br /&gt;
			textCellDiv&lt;br /&gt;
				:tag(&#039;span&#039;)&lt;br /&gt;
				:addClass(&#039;hide-when-compact&#039;)&lt;br /&gt;
				:wikitext(self.info and (&#039; &#039; .. self.info) or nil)&lt;br /&gt;
		end&lt;br /&gt;
		if self.removalNotice then&lt;br /&gt;
			textCellDiv:tag(&#039;span&#039;)&lt;br /&gt;
				:addClass(&#039;hide-when-compact&#039;)&lt;br /&gt;
				:tag(&#039;i&#039;)&lt;br /&gt;
					:wikitext(string.format(&amp;quot; (%s)&amp;quot;, self.removalNotice))&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		-- Default text formatting - anything goes.&lt;br /&gt;
		textCell&lt;br /&gt;
			:cssText(self.textstyle or nil)&lt;br /&gt;
			:wikitext(self.text or nil)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Add the right-hand image.&lt;br /&gt;
	if self.imageRight then&lt;br /&gt;
		local imageRightCell = flex_container:tag(&#039;div&#039;):addClass(&#039;mbox-imageright&#039;)&lt;br /&gt;
		imageRightCell&lt;br /&gt;
			:addClass(self.imageRightClass)&lt;br /&gt;
			:wikitext(self.imageRight or nil)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	mbox:node(flex_container)&lt;br /&gt;
&lt;br /&gt;
	-- Add the below row.&lt;br /&gt;
	if self.below then&lt;br /&gt;
		mbox:tag(&#039;div&#039;)&lt;br /&gt;
			:addClass(&#039;mbox-text mbox-below&#039;)&lt;br /&gt;
			:cssText(self.textstyle or nil)&lt;br /&gt;
			:wikitext(self.below or nil)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Add error message for invalid type parameters.&lt;br /&gt;
	if self.invalidTypeError then&lt;br /&gt;
		root:tag(&#039;div&#039;)&lt;br /&gt;
			:addClass(&#039;mbox-invalid-type&#039;)&lt;br /&gt;
			:wikitext(string.format(&lt;br /&gt;
				&#039;This message box is using an invalid &amp;quot;type=%s&amp;quot; parameter and needs fixing.&#039;,&lt;br /&gt;
				self.type or &#039;&#039;&lt;br /&gt;
			))&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Add categories.&lt;br /&gt;
	root:wikitext(self:renderCategories() or nil)&lt;br /&gt;
&lt;br /&gt;
	return tostring(root)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function MessageBox:export()&lt;br /&gt;
&lt;br /&gt;
	local root = mw.html.create()&lt;br /&gt;
&lt;br /&gt;
	-- Add the subst check error.&lt;br /&gt;
	if self.isSubstituted and self.name then&lt;br /&gt;
		root:tag(&#039;b&#039;)&lt;br /&gt;
			:addClass(&#039;error&#039;)&lt;br /&gt;
			:wikitext(string.format(&lt;br /&gt;
				&#039;Template &amp;lt;code&amp;gt;%s[[Template:%s|%s]]%s&amp;lt;/code&amp;gt; has been incorrectly substituted.&#039;,&lt;br /&gt;
				mw.text.nowiki(&#039;{{&#039;), self.name, self.name, mw.text.nowiki(&#039;}}&#039;)&lt;br /&gt;
			))&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local frame = mw.getCurrentFrame()&lt;br /&gt;
	root:wikitext(frame:extensionTag{&lt;br /&gt;
		name = &#039;templatestyles&#039;,&lt;br /&gt;
		args = { src = self.base_templatestyles },&lt;br /&gt;
	})&lt;br /&gt;
	-- Add support for a single custom templatestyles sheet. Undocumented as&lt;br /&gt;
	-- need should be limited and many templates using mbox are substed; we&lt;br /&gt;
	-- don&#039;t want to spread templatestyles sheets around to arbitrary places&lt;br /&gt;
	if self.templatestyles then&lt;br /&gt;
		root:wikitext(frame:extensionTag{&lt;br /&gt;
			name = &#039;templatestyles&#039;,&lt;br /&gt;
			args = { src = self.templatestyles },&lt;br /&gt;
		})&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Create the box table.&lt;br /&gt;
	local boxTable = root:tag(&#039;table&#039;)&lt;br /&gt;
	boxTable:attr(&#039;id&#039;, self.id or nil)&lt;br /&gt;
	for i, class in ipairs(self.classes or {}) do&lt;br /&gt;
		boxTable:addClass(class or nil)&lt;br /&gt;
	end&lt;br /&gt;
	boxTable&lt;br /&gt;
		:cssText(self.style or nil)&lt;br /&gt;
		:attr(&#039;role&#039;, &#039;presentation&#039;)&lt;br /&gt;
&lt;br /&gt;
	if self.attrs then&lt;br /&gt;
		boxTable:attr(self.attrs)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Add the left-hand image.&lt;br /&gt;
	local row = boxTable:tag(&#039;tr&#039;)&lt;br /&gt;
	if self.imageLeft then&lt;br /&gt;
		local imageLeftCell = row:tag(&#039;td&#039;):addClass(&#039;mbox-image&#039;)&lt;br /&gt;
		if self.imageCellDiv then&lt;br /&gt;
			-- If we are using a div, redefine imageLeftCell so that the image&lt;br /&gt;
			-- is inside it. Divs use style=&amp;quot;width: 52px;&amp;quot;, which limits the&lt;br /&gt;
			-- image width to 52px. If any images in a div are wider than that,&lt;br /&gt;
			-- they may overlap with the text or cause other display problems.&lt;br /&gt;
			imageLeftCell = imageLeftCell:tag(&#039;div&#039;):addClass(&#039;mbox-image-div&#039;)&lt;br /&gt;
		end&lt;br /&gt;
		imageLeftCell&lt;br /&gt;
			:addClass(self.imageLeftClass)&lt;br /&gt;
			:wikitext(self.imageLeft or nil)&lt;br /&gt;
	elseif self.imageEmptyCell then&lt;br /&gt;
		-- Some message boxes define an empty cell if no image is specified, and&lt;br /&gt;
		-- some don&#039;t. The old template code in templates where empty cells are&lt;br /&gt;
		-- specified gives the following hint: &amp;quot;No image. Cell with some width&lt;br /&gt;
		-- or padding necessary for text cell to have 100% width.&amp;quot;&lt;br /&gt;
		row:tag(&#039;td&#039;)&lt;br /&gt;
			:addClass(&#039;mbox-empty-cell&#039;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Add the text.&lt;br /&gt;
	local textCell = row:tag(&#039;td&#039;):addClass(&#039;mbox-text&#039;)&lt;br /&gt;
	if self.useCollapsibleTextFields then&lt;br /&gt;
		-- The message box uses advanced text parameters that allow things to be&lt;br /&gt;
		-- collapsible. At the moment, only ambox uses this.&lt;br /&gt;
		textCell:cssText(self.textstyle or nil)&lt;br /&gt;
		local textCellDiv = textCell:tag(&#039;div&#039;)&lt;br /&gt;
		textCellDiv&lt;br /&gt;
			:addClass(&#039;mbox-text-span&#039;)&lt;br /&gt;
			:wikitext(self.issue or nil)&lt;br /&gt;
		if (self.talk or self.fix) then&lt;br /&gt;
			textCellDiv:tag(&#039;span&#039;)&lt;br /&gt;
				:addClass(&#039;hide-when-compact&#039;)&lt;br /&gt;
				:wikitext(self.talk and (&#039; &#039; .. self.talk) or nil)&lt;br /&gt;
				:wikitext(self.fix and (&#039; &#039; .. self.fix) or nil)&lt;br /&gt;
		end&lt;br /&gt;
		textCellDiv:wikitext(self.date and (&#039; &#039; .. self.date) or nil)&lt;br /&gt;
		if self.info and not self.isSmall then&lt;br /&gt;
			textCellDiv&lt;br /&gt;
				:tag(&#039;span&#039;)&lt;br /&gt;
				:addClass(&#039;hide-when-compact&#039;)&lt;br /&gt;
				:wikitext(self.info and (&#039; &#039; .. self.info) or nil)&lt;br /&gt;
		end&lt;br /&gt;
		if self.removalNotice then&lt;br /&gt;
			textCellDiv:tag(&#039;span&#039;)&lt;br /&gt;
				:addClass(&#039;hide-when-compact&#039;)&lt;br /&gt;
				:tag(&#039;i&#039;)&lt;br /&gt;
					:wikitext(string.format(&amp;quot; (%s)&amp;quot;, self.removalNotice))&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		-- Default text formatting - anything goes.&lt;br /&gt;
		textCell&lt;br /&gt;
			:cssText(self.textstyle or nil)&lt;br /&gt;
			:wikitext(self.text or nil)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Add the right-hand image.&lt;br /&gt;
	if self.imageRight then&lt;br /&gt;
		local imageRightCell = row:tag(&#039;td&#039;):addClass(&#039;mbox-imageright&#039;)&lt;br /&gt;
		if self.imageCellDiv then&lt;br /&gt;
			-- If we are using a div, redefine imageRightCell so that the image&lt;br /&gt;
			-- is inside it.&lt;br /&gt;
			imageRightCell = imageRightCell:tag(&#039;div&#039;):addClass(&#039;mbox-image-div&#039;)&lt;br /&gt;
		end&lt;br /&gt;
		imageRightCell&lt;br /&gt;
			:addClass(self.imageRightClass)&lt;br /&gt;
			:wikitext(self.imageRight or nil)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Add the below row.&lt;br /&gt;
	if self.below then&lt;br /&gt;
		boxTable:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;td&#039;)&lt;br /&gt;
				:attr(&#039;colspan&#039;, self.imageRight and &#039;3&#039; or &#039;2&#039;)&lt;br /&gt;
				:addClass(&#039;mbox-text&#039;)&lt;br /&gt;
				:cssText(self.textstyle or nil)&lt;br /&gt;
				:wikitext(self.below or nil)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Add error message for invalid type parameters.&lt;br /&gt;
	if self.invalidTypeError then&lt;br /&gt;
		root:tag(&#039;div&#039;)&lt;br /&gt;
			:addClass(&#039;mbox-invalid-type&#039;)&lt;br /&gt;
			:wikitext(string.format(&lt;br /&gt;
				&#039;This message box is using an invalid &amp;quot;type=%s&amp;quot; parameter and needs fixing.&#039;,&lt;br /&gt;
				self.type or &#039;&#039;&lt;br /&gt;
			))&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Add categories.&lt;br /&gt;
	root:wikitext(self:renderCategories() or nil)&lt;br /&gt;
&lt;br /&gt;
	return tostring(root)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Exports&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local p, mt = {}, {}&lt;br /&gt;
&lt;br /&gt;
function p._exportClasses()&lt;br /&gt;
	-- For testing.&lt;br /&gt;
	return {&lt;br /&gt;
		MessageBox = MessageBox&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main(boxType, args, cfgTables)&lt;br /&gt;
	local box = MessageBox.new(boxType, args, cfgTables or mw.loadData(CONFIG_MODULE))&lt;br /&gt;
	box:setParameters()&lt;br /&gt;
	box:setCategories()&lt;br /&gt;
	-- DIV MIGRATION CONDITIONAL&lt;br /&gt;
	if box.cfg.div_structure then&lt;br /&gt;
		return box:exportDiv()&lt;br /&gt;
	end&lt;br /&gt;
	-- END DIV MIGRATION CONDITIONAL&lt;br /&gt;
	return box:export()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function mt.__index(t, k)&lt;br /&gt;
	return function (frame)&lt;br /&gt;
		if not getArgs then&lt;br /&gt;
			getArgs = require(&#039;Module:Arguments&#039;).getArgs&lt;br /&gt;
		end&lt;br /&gt;
		return t.main(k, getArgs(frame, {trim = false, removeBlanks = false}))&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return setmetatable(p, mt)&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=Module:Yesno&amp;diff=120493</id>
		<title>Module:Yesno</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=Module:Yesno&amp;diff=120493"/>
		<updated>2026-06-24T20:29:38Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- Function allowing for consistent treatment of boolean-like wikitext input.&lt;br /&gt;
-- It works similarly to the template {{yesno}}.&lt;br /&gt;
&lt;br /&gt;
return function (val, default)&lt;br /&gt;
	-- If your wiki uses non-ascii characters for any of &amp;quot;yes&amp;quot;, &amp;quot;no&amp;quot;, etc., you&lt;br /&gt;
	-- should replace &amp;quot;val:lower()&amp;quot; with &amp;quot;mw.ustring.lower(val)&amp;quot; in the&lt;br /&gt;
	-- following line.&lt;br /&gt;
	val = type(val) == &#039;string&#039; and val:lower() or val&lt;br /&gt;
	if val == nil then&lt;br /&gt;
		return nil&lt;br /&gt;
	elseif val == true &lt;br /&gt;
		or val == &#039;yes&#039;&lt;br /&gt;
		or val == &#039;y&#039;&lt;br /&gt;
		or val == &#039;true&#039;&lt;br /&gt;
		or val == &#039;t&#039;&lt;br /&gt;
		or val == &#039;on&#039;&lt;br /&gt;
		or tonumber(val) == 1&lt;br /&gt;
	then&lt;br /&gt;
		return true&lt;br /&gt;
	elseif val == false&lt;br /&gt;
		or val == &#039;no&#039;&lt;br /&gt;
		or val == &#039;n&#039;&lt;br /&gt;
		or val == &#039;false&#039;&lt;br /&gt;
		or val == &#039;f&#039;&lt;br /&gt;
		or val == &#039;off&#039;&lt;br /&gt;
		or tonumber(val) == 0&lt;br /&gt;
	then&lt;br /&gt;
		return false&lt;br /&gt;
	else&lt;br /&gt;
		return default&lt;br /&gt;
	end&lt;br /&gt;
end&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadgets-definition&amp;diff=120491</id>
		<title>MediaWiki:Gadgets-definition</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadgets-definition&amp;diff=120491"/>
		<updated>2026-06-24T20:29:38Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&#039;&#039;&#039;Changes to this page should first be discussed on [[Wikipedia:Village pump (technical)]] or [[Wikipedia talk:Gadget]].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Links to view and manage the gadget descriptions appear on [[Special:Gadgets]].&lt;br /&gt;
{{#invoke:Validate gadgets|validate}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== browsing ==&lt;br /&gt;
* modrollback [ResourceLoader |rights=rollback] |modrollback.js&lt;br /&gt;
* confirmationRollback-mobile [ResourceLoader |default |rights=rollback |dependencies=mediawiki.util] |confirmationRollback-mobile.js&lt;br /&gt;
* removeAccessKeys [ResourceLoader |dependencies=user, mediawiki.util] |removeAccessKeys.js&lt;br /&gt;
* searchFocus [ResourceLoader] |searchFocus.js&lt;br /&gt;
* GoogleTrans [ResourceLoader] |GoogleTrans.js&lt;br /&gt;
* ImageAnnotator [ResourceLoader] |ImageAnnotator.js&lt;br /&gt;
* imagelinks [ResourceLoader |dependencies=mediawiki.util] |imagelinks.js&lt;br /&gt;
* Navigation_popups [ResourceLoader |dependencies=mediawiki.api, mediawiki.user, mediawiki.util, user.options, mediawiki.jqueryMsg |type=general] |popups.js |navpop.css&lt;br /&gt;
* exlinks [ResourceLoader |dependencies=mediawiki.util] |exlinks.js&lt;br /&gt;
* search-new-tab [ResourceLoader] |search-new-tab.js&lt;br /&gt;
* PrintOptions [ResourceLoader] |PrintOptions.js&lt;br /&gt;
* revisionjumper [ResourceLoader] |revisionjumper.js&lt;br /&gt;
* Twinkle [ResourceLoader |dependencies=ext.gadget.morebits, ext.gadget.select2, mediawiki.language |rights=autoconfirmed |type=general |peers=Twinkle-pagestyles] |Twinkle.js |Twinkle.css |twinklearv.js |twinklewarn.js |twinkleblock.js |twinklewelcome.js |twinkletalkback.js |twinklespeedy.js |twinkleprod.js |twinklexfd.js |twinkleimage.js |twinkleprotect.js |twinkletag.js |twinklediff.js |twinkleunlink.js |twinklerollback.js |twinkledeprod.js |twinklebatchdelete.js |twinklebatchprotect.js |twinklebatchundelete.js |twinkleconfig.js&lt;br /&gt;
* morebits [ResourceLoader |dependencies=mediawiki.user, mediawiki.util, mediawiki.Title, mediawiki.api |hidden] |morebits.js |morebits.css&lt;br /&gt;
* Twinkle-pagestyles [hidden |skins=vector, vector-2022] |Twinkle-pagestyles.css&lt;br /&gt;
* select2 [ResourceLoader |hidden] |select2.min.js |select2.min.css&lt;br /&gt;
* HideCentralNotice [ResourceLoader |type=general] |HideCentralNotice.js |HideCentralNotice.css&lt;br /&gt;
* ReferenceTooltips [ResourceLoader |default |skins=vector, vector-2022, monobook, timeless, modern, cologneblue |type=general |dependencies=mediawiki.cookie, jquery.client] |ReferenceTooltips.js |ReferenceTooltips.css&lt;br /&gt;
* formWizard [ResourceLoader |default |rights=minoredit |namespaces=4] |formWizard.js&lt;br /&gt;
* formWizard-core [ResourceLoader |hidden |dependencies=mediawiki.api, mediawiki.cookie, mediawiki.user, jquery.chosen, jquery.ui, user.options] |formWizard-core.js |formWizard.css&lt;br /&gt;
* Prosesize [ResourceLoader |dependencies=mediawiki.api, mediawiki.util] |Prosesize.js |Prosesize.css&lt;br /&gt;
* find-archived-section [ResourceLoader] |find-archived-section.js&lt;br /&gt;
&lt;br /&gt;
== watchlist ==&lt;br /&gt;
&amp;lt;!-- rights=viewmywatchlist limits these default gadgets to logged-in users. --&amp;gt;&lt;br /&gt;
* geonotice [ResourceLoader |default |rights=viewmywatchlist] |geonotice.js&lt;br /&gt;
* geonotice-core [ResourceLoader |dependencies=mediawiki.util, mediawiki.storage |hidden] |geonotice-list.js |geonotice-core.js |geonotice-core.css&lt;br /&gt;
* watchlist-notice [ResourceLoader |default |rights=viewmywatchlist |namespaces=-1] |watchlist-notice.js&lt;br /&gt;
* watchlist-notice-core [ResourceLoader |dependencies=mediawiki.storage |hidden] |watchlist-notice-core.js&lt;br /&gt;
* WatchlistBase [ResourceLoader |default |rights=viewmywatchlist |skins=vector, vector-2022, monobook, modern |namespaces=-1] |WatchlistBase.css&lt;br /&gt;
* WatchlistGreenIndicators [ResourceLoader |default |rights=viewmywatchlist |peers=WatchlistBase |skins=vector, vector-2022 |namespaces=-1] |WatchlistGreenIndicators.css&lt;br /&gt;
* WatchlistGreenIndicatorsMono [ResourceLoader |default |rights=viewmywatchlist |peers=WatchlistBase |skins=monobook, modern |namespaces=-1] |WatchlistGreenIndicatorsMono.css&lt;br /&gt;
* WatchlistChangesBold [ResourceLoader |peers=WatchlistBase |namespaces=-1] |WatchlistChangesBold.css&lt;br /&gt;
* SubtleUpdatemarker [ResourceLoader |default |rights=viewmywatchlist |skins=vector, vector-2022, monobook, modern] |SubtleUpdatemarker.css&lt;br /&gt;
&lt;br /&gt;
== editing ==&lt;br /&gt;
* defaultsummaries [ResourceLoader |dependencies=oojs-ui-core] |defaultsummaries.js&lt;br /&gt;
* citations [ResourceLoader |dependencies=mediawiki.util] |citations.js&lt;br /&gt;
* DotsSyntaxHighlighter [ResourceLoader |actions=edit] |DotsSyntaxHighlighter.js&lt;br /&gt;
* HotCat [ResourceLoader |rights=edit, minoredit] |HotCat.js&lt;br /&gt;
* wikEdDiff [ResourceLoader] |wikEdDiff.js&lt;br /&gt;
* ProveIt [ResourceLoader |namespaces=0, 2, 10, 118] |ProveIt.js&lt;br /&gt;
* ProveIt-classic [ResourceLoader |type=general |dependencies=jquery.ui, jquery.textSelection, mediawiki.util |actions=edit] |ProveIt-classic.css |ProveIt-classic.js&lt;br /&gt;
* Shortdesc-helper [ResourceLoader |dependencies=mediawiki.api, user.options, mediawiki.util, ext.gadget.libSettings |skins=vector, vector-2022, monobook, modern, timeless |peers=Shortdesc-helper-pagestyles-vector] |Shortdesc-helper.js |Shortdesc-helper.css&lt;br /&gt;
* Shortdesc-helper-pagestyles-vector [hidden |skins=vector, vector-2022] |Shortdesc-helper-pagestyles-vector.css&lt;br /&gt;
* libSettings [ResourceLoader |hidden |dependencies=user.options] |libSettings.js&lt;br /&gt;
* wikEd [ResourceLoader |dependencies=jquery.textSelection, user.options] |wikEd.js&lt;br /&gt;
* afchelper [ResourceLoader |dependencies=mediawiki.api, mediawiki.util, mediawiki.user, jquery.chosen, jquery.spinner, jquery.ui |namespaces=2, 118] |afchelper.js |afchelper.css&lt;br /&gt;
* charinsert [ResourceLoader |default |actions=edit] |charinsert.js&lt;br /&gt;
* charinsert-core [ResourceLoader |hidden |dependencies=jquery.textSelection, user, mediawiki.storage] |charinsert-styles.css |charinsert-core.js&lt;br /&gt;
* legacyToolbar [ResourceLoader] |legacyToolbar.js |extra-toolbar-buttons-core.js &lt;br /&gt;
* refToolbar [ResourceLoader |default |dependencies=mediawiki.util |actions=edit |contentModels=wikitext] |refToolbar.js&lt;br /&gt;
* refToolbarBase [ResourceLoader |hidden] |refToolbarBase.js&lt;br /&gt;
&lt;br /&gt;
== appearance ==&lt;br /&gt;
* edittop [ResourceLoader |dependencies=user.options, mediawiki.util |type=general] |edittop.js |edittop.css&lt;br /&gt;
* UTCLiveClock [ResourceLoader |supportsUrlLoad |type=general |dependencies=mediawiki.util, mediawiki.api |peers=UTCLiveClock-pagestyles] |UTCLiveClock.js |UTCLiveClock.css&lt;br /&gt;
* UTCLiveClock-pagestyles [hidden |skins=vector, vector-2022, monobook] |UTCLiveClock-pagestyles.css&lt;br /&gt;
* purgetab [ResourceLoader |dependencies=mediawiki.util, mediawiki.api] |purgetab.js&lt;br /&gt;
* ExternalSearch [ResourceLoader |namespaces=-1] |externalsearch.js&lt;br /&gt;
* CollapsibleNav [ResourceLoader |dependencies=jquery.makeCollapsible, mediawiki.storage |skins=vector, vector-2022] |CollapsibleNav.js |CollapsibleNav.css&lt;br /&gt;
* MenuTabsToggle [ResourceLoader |dependencies=mediawiki.cookie |skins=vector, vector-2022 |type=general] |MenuTabsToggle.js |MenuTabsToggle.css&lt;br /&gt;
* dropdown-menus [ResourceLoader |dependencies=mediawiki.api, mediawiki.util, mediawiki.Title, user.options |peers=dropdown-menus-pagestyles |skins=vector, vector-2022, monobook, timeless, modern, cologneblue] |MoreMenu.enwiki.js |dropdown-menus.js&lt;br /&gt;
* dropdown-menus-pagestyles [hidden] |dropdown-menus-pagestyles.css&lt;br /&gt;
* CategoryAboveAll [ResourceLoader |skins=monobook] |CategoryAboveAll.js&lt;br /&gt;
* addsection-plus [ResourceLoader] |addsection-plus.js&lt;br /&gt;
* CommentsInLocalTime [ResourceLoader] |CommentsInLocalTime.js&lt;br /&gt;
* OldDiff [ResourceLoader] |OldDiff.css&lt;br /&gt;
* NoAnimations [ResourceLoader] |NoAnimations.js&lt;br /&gt;
* disablesuggestions [ResourceLoader] |disablesuggestions.js&lt;br /&gt;
* NoSmallFonts [ResourceLoader] |NoSmallFonts.css&lt;br /&gt;
* topalert [ResourceLoader |type=general] |topalert.js |topalert.css&lt;br /&gt;
* metadata [ResourceLoader |dependencies=mediawiki.util |type=general] |metadata.js |metadata.css&lt;br /&gt;
* JustifyParagraphs [ResourceLoader] |JustifyParagraphs.css&lt;br /&gt;
* righteditlinks [ResourceLoader] |righteditlinks.css&lt;br /&gt;
* PrettyLog [ResourceLoader |dependencies=mediawiki.util |type=general] |PrettyLog.js |PrettyLog.css&lt;br /&gt;
* switcher [ResourceLoader |default] |switcher.js&lt;br /&gt;
* SidebarTranslate [ResourceLoader |type=general] |SidebarTranslate.js |SidebarTranslate.css&lt;br /&gt;
* Blackskin [ResourceLoader |skins=monobook, vector, vector-2022 |supportsUrlLoad] |Blackskin.css&lt;br /&gt;
* dark-mode-toggle [ResourceLoader |dependencies=mediawiki.util, mediawiki.api, mediawiki.storage |peers=dark-mode-toggle-pagestyles] |dark-mode-toggle.js&lt;br /&gt;
* dark-mode-toggle-pagestyles [hidden |skins=vector, vector-2022, minerva, monobook] |dark-mode-toggle-pagestyles.css&lt;br /&gt;
* VectorClassic [ResourceLoader |skins=vector, vector-2022] |VectorClassic.css&lt;br /&gt;
* widensearch [ResourceLoader |skins=vector, vector-2022] |widensearch.css&lt;br /&gt;
* DisambiguationLinks [ResourceLoader] |DisambiguationLinks.css&lt;br /&gt;
* markblocked [ResourceLoader |dependencies=mediawiki.util, mediawiki.page.ready, mediawiki.Title] |markblocked.js&lt;br /&gt;
* responsiveContent [ResourceLoader |type=general |skins=vector|peers=responsiveContentBase] |responsiveContent.js&lt;br /&gt;
* responsiveContentTimeless [ResourceLoader |type=general |skins=timeless |default |peers=responsiveContentBaseTimeless] |responsiveContentTimeless.js&lt;br /&gt;
* responsiveContentBase [ResourceLoader |type=styles |hidden |skins=vector] |responsiveContentBase.css&lt;br /&gt;
* responsiveContentBaseTimeless [ResourceLoader |type=styles |hidden |skins=timeless] |responsiveContentBaseTimeless.css&lt;br /&gt;
* HideInterwikiSearchResults [ResourceLoader |type=styles] |HideInterwikiSearchResults.css&lt;br /&gt;
* XTools-ArticleInfo [ResourceLoader] |XTools-ArticleInfo.js&lt;br /&gt;
* remove-sticky-decoration [ResourceLoader]|remove-sticky-decoration.css&lt;br /&gt;
* InterProjectLinks[ResourceLoader|type=general|skins=vector,vector-2022,monobook,timeless,modern,cologneblue]|InterProjectLinks.js|InterProjectLinks.css&lt;br /&gt;
&lt;br /&gt;
== advanced ==&lt;br /&gt;
* RegexMenuFramework [ResourceLoader |hidden] |RegexMenuFramework.js&lt;br /&gt;
* ShowMessageNames [ResourceLoader |dependencies=mediawiki.util] |ShowMessageNames.js&lt;br /&gt;
* DebugMode [ResourceLoader |dependencies=mediawiki.util] |DebugMode.js&lt;br /&gt;
* contribsrange [ResourceLoader |dependencies=mediawiki.util, jquery.spinner] |contribsrange.js&lt;br /&gt;
* BugStatusUpdate [ResourceLoader] |BugStatusUpdate.js&lt;br /&gt;
* RTRC [ResourceLoader] |RTRC.js&lt;br /&gt;
* script-installer [ResourceLoader |dependencies=mediawiki.ui.button] |script-installer.js&lt;br /&gt;
&lt;br /&gt;
== maintenance ==&lt;br /&gt;
* XFDcloser [ResourceLoader |dependencies=mediawiki.user |rights=extendedconfirmed |type=general] |XFDcloser.js&lt;br /&gt;
* XFDcloser-core [ResourceLoader |dependencies=mediawiki.util, mediawiki.api, mediawiki.Title, oojs-ui-core, oojs-ui-widgets, oojs-ui-windows, oojs-ui.styles.icons-interactions, oojs-ui.styles.icons-content, oojs-ui.styles.icons-moderation, oojs-ui.styles.icons-alerts |hidden |type=general] |XFDcloser-core.js |XFDcloser-core.css&lt;br /&gt;
* XFDcloser-core-beta [ResourceLoader |dependencies=mediawiki.util, mediawiki.api, mediawiki.Title, oojs-ui-core, oojs-ui-widgets, oojs-ui-windows, oojs-ui.styles.icons-interactions, oojs-ui.styles.icons-content, oojs-ui.styles.icons-moderation, oojs-ui.styles.icons-alerts |hidden |type=general] |XFDcloser-core-beta.js |XFDcloser-core-beta.css&lt;br /&gt;
* libExtraUtil [ResourceLoader |hidden] |libExtraUtil.js&lt;br /&gt;
&lt;br /&gt;
== test ==&lt;br /&gt;
* mobile-sidebar [ResourceLoader |skins=vector, vector-2022] |mobile-sidebar.js |mobile-sidebar.css&lt;br /&gt;
* addMe [ResourceLoader] |addMe.js |addMe.css&lt;br /&gt;
* NewImageThumb [ResourceLoader |skins=vector, vector-2022] |NewImageThumb.js |NewImageThumb.css&lt;br /&gt;
* StickyTableHeaders [ResourceLoader |type=general] |StickyTableHeaders.js |StickyTableHeaders.css&lt;br /&gt;
* MobileMaps [ResourceLoader |skins=minerva] |mobilemaps.js&lt;br /&gt;
* ShowJavascriptErrors [ResourceLoader |type=general] |ShowJavascriptErrors.js&lt;br /&gt;
* PageDescriptions [ResourceLoader |type=general |dependencies=mediawiki.api |skins=vector, vector-2022, monobook, modern] |Page_descriptions.js&lt;br /&gt;
* autonum [ResourceLoader] |autonum.css |autonum.js&lt;br /&gt;
&lt;br /&gt;
== template-gadgets ==&lt;br /&gt;
* Vivarium[ResourceLoader|default|categories=Pages using gadget Vivarium]|Vivarium.js|Vivarium.css&lt;br /&gt;
* WikiMiniAtlas [ ResourceLoader | default | categories = Pages using gadget WikiMiniAtlas] | WikiMiniAtlas.js&lt;br /&gt;
* ImageStackPopup [ ResourceLoader | default | categories = Pages using gadget ImageStackPopup ] | ImageStackPopup.js | ImageStackPopup.css&lt;br /&gt;
* Calculator [ResourceLoader | default | categories = Pages using gadget Calculator ] | calculator.js |calculator.css&lt;br /&gt;
* owidslider [ResourceLoader|default|categories=Pages using gadget owidslider]|owidslider.js|owidslider.css&lt;br /&gt;
&lt;br /&gt;
== modules ==&lt;br /&gt;
* libLua  [ResourceLoader |dependencies=mediawiki.api |hidden] |libLua.js&lt;br /&gt;
* libSensitiveIPs  [ResourceLoader |dependencies=ext.gadget.libLua |hidden] |libSensitiveIPs.js&lt;br /&gt;
* dark-mode [ResourceLoader |supportsUrlLoad |skins=vector, vector-2022, monobook, modern, minerva, timeless] |dark-mode.css&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-externalsearch.js&amp;diff=120489</id>
		<title>MediaWiki:Gadget-externalsearch.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-externalsearch.js&amp;diff=120489"/>
		<updated>2026-06-24T20:26:57Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: Protected &amp;quot;MediaWiki:Gadget-externalsearch.js&amp;quot; ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite)) [cascading]&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/** Change Special:Search to use a drop-down menu *******************************************************&lt;br /&gt;
  *&lt;br /&gt;
  *  Description: Change Special:Search to use a drop-down menu, with the default being&lt;br /&gt;
  *               the internal MediaWiki engine&lt;br /&gt;
  *  Created by: [[User:Gracenotes]]&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
function SpecialSearchEnhanced() {&lt;br /&gt;
    var createOption = function(site, action, mainQ, addQ, addV) {&lt;br /&gt;
        var opt = document.createElement(&#039;option&#039;);&lt;br /&gt;
        opt.appendChild(document.createTextNode(site));&lt;br /&gt;
        window.searchEngines.push([action, mainQ, addQ, addV]);&lt;br /&gt;
        return opt;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (document.forms.powersearch)&lt;br /&gt;
        var searchForm = document.forms.powersearch;&lt;br /&gt;
    if (document.forms.search)&lt;br /&gt;
        var searchForm = document.forms.search;&lt;br /&gt;
&lt;br /&gt;
    if (searchForm.lsearchbox) {&lt;br /&gt;
        var searchBox = searchForm.lsearchbox;&lt;br /&gt;
    } else {&lt;br /&gt;
        var searchBox = searchForm.search;&lt;br /&gt;
    }&lt;br /&gt;
    var selectBox = document.createElement(&#039;select&#039;);&lt;br /&gt;
    selectBox.id = &#039;searchEngine&#039;;&lt;br /&gt;
    searchForm.onsubmit = function() {&lt;br /&gt;
        var optSelected = window.searchEngines[document.getElementById(&#039;searchEngine&#039;).selectedIndex];&lt;br /&gt;
        searchForm.action = optSelected[0];&lt;br /&gt;
        searchBox.name = optSelected[1];&lt;br /&gt;
        searchForm.title.value = optSelected[3];&lt;br /&gt;
        searchForm.title.name = optSelected[2];&lt;br /&gt;
    }&lt;br /&gt;
    selectBox.appendChild(createOption(&#039;English Wikipedia&#039;, mw.config.get( &#039;wgScript&#039; ), &#039;search&#039;, &#039;title&#039;, &#039;Special:Search&#039;));&lt;br /&gt;
    selectBox.appendChild(createOption(&#039;Google&#039;, &#039;https://www.google.com/search&#039;, &#039;q&#039;, &#039;sitesearch&#039;, &#039;en.wikipedia.org&#039;));&lt;br /&gt;
    selectBox.appendChild(createOption(&#039;Yahoo&#039;, &#039;https://search.yahoo.com/search&#039;, &#039;p&#039;, &#039;vs&#039;, &#039;en.wikipedia.org&#039;));&lt;br /&gt;
    selectBox.appendChild(createOption(&#039;Bing&#039;, &#039;https://www.bing.com/search&#039;, &#039;q&#039;, &#039;q1&#039;, &#039;site:https://en.wikipedia.org&#039;));&lt;br /&gt;
    selectBox.appendChild(createOption(&#039;Wikiwix&#039;, &#039;https://www.wikiwix.com/&#039;, &#039;action&#039;, &#039;lang&#039;, &#039;en&#039;));&lt;br /&gt;
    selectBox.appendChild(createOption(&#039;Exalead&#039;, &#039;https://www.exalead.com/wikipedia/results&#039;, &#039;q&#039;, &#039;language&#039;, &#039;en&#039;));&lt;br /&gt;
    searchBox.style.marginLeft = &#039;0px&#039;;&lt;br /&gt;
    if (document.getElementById(&#039;loadStatus&#039;)) {&lt;br /&gt;
        var lStat = document.getElementById(&#039;loadStatus&#039;);&lt;br /&gt;
    } else {&lt;br /&gt;
        var lStat = searchForm.title;&lt;br /&gt;
        if( typeof lStat === &#039;object&#039;  &amp;amp;&amp;amp; typeof lStat.length === &#039;number&#039; ) lStat = lStat[0];&lt;br /&gt;
    }&lt;br /&gt;
    lStat.parentNode.insertBefore(selectBox, lStat);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
window.searchEngines = [];&lt;br /&gt;
&lt;br /&gt;
// Script is specific to Special:Search&lt;br /&gt;
if ( mw.config.get( &#039;wgCanonicalSpecialPageName&#039; ) === &#039;Search&#039;){&lt;br /&gt;
  $(SpecialSearchEnhanced);&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-externalsearch.js&amp;diff=120488</id>
		<title>MediaWiki:Gadget-externalsearch.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-externalsearch.js&amp;diff=120488"/>
		<updated>2026-06-24T20:26:46Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: ←Created page with &amp;#039;/** Change Special:Search to use a drop-down menu *******************************************************   *   *  Description: Change Special:Search to use a drop-down menu, with the default being   *               the internal MediaWiki engine   *  Created by: User:Gracenotes   */  function SpecialSearchEnhanced() {     var createOption = function(site, action, mainQ, addQ, addV) {         var opt = document.createElement(&amp;#039;option&amp;#039;);         opt.append...&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/** Change Special:Search to use a drop-down menu *******************************************************&lt;br /&gt;
  *&lt;br /&gt;
  *  Description: Change Special:Search to use a drop-down menu, with the default being&lt;br /&gt;
  *               the internal MediaWiki engine&lt;br /&gt;
  *  Created by: [[User:Gracenotes]]&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
function SpecialSearchEnhanced() {&lt;br /&gt;
    var createOption = function(site, action, mainQ, addQ, addV) {&lt;br /&gt;
        var opt = document.createElement(&#039;option&#039;);&lt;br /&gt;
        opt.appendChild(document.createTextNode(site));&lt;br /&gt;
        window.searchEngines.push([action, mainQ, addQ, addV]);&lt;br /&gt;
        return opt;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (document.forms.powersearch)&lt;br /&gt;
        var searchForm = document.forms.powersearch;&lt;br /&gt;
    if (document.forms.search)&lt;br /&gt;
        var searchForm = document.forms.search;&lt;br /&gt;
&lt;br /&gt;
    if (searchForm.lsearchbox) {&lt;br /&gt;
        var searchBox = searchForm.lsearchbox;&lt;br /&gt;
    } else {&lt;br /&gt;
        var searchBox = searchForm.search;&lt;br /&gt;
    }&lt;br /&gt;
    var selectBox = document.createElement(&#039;select&#039;);&lt;br /&gt;
    selectBox.id = &#039;searchEngine&#039;;&lt;br /&gt;
    searchForm.onsubmit = function() {&lt;br /&gt;
        var optSelected = window.searchEngines[document.getElementById(&#039;searchEngine&#039;).selectedIndex];&lt;br /&gt;
        searchForm.action = optSelected[0];&lt;br /&gt;
        searchBox.name = optSelected[1];&lt;br /&gt;
        searchForm.title.value = optSelected[3];&lt;br /&gt;
        searchForm.title.name = optSelected[2];&lt;br /&gt;
    }&lt;br /&gt;
    selectBox.appendChild(createOption(&#039;English Wikipedia&#039;, mw.config.get( &#039;wgScript&#039; ), &#039;search&#039;, &#039;title&#039;, &#039;Special:Search&#039;));&lt;br /&gt;
    selectBox.appendChild(createOption(&#039;Google&#039;, &#039;https://www.google.com/search&#039;, &#039;q&#039;, &#039;sitesearch&#039;, &#039;en.wikipedia.org&#039;));&lt;br /&gt;
    selectBox.appendChild(createOption(&#039;Yahoo&#039;, &#039;https://search.yahoo.com/search&#039;, &#039;p&#039;, &#039;vs&#039;, &#039;en.wikipedia.org&#039;));&lt;br /&gt;
    selectBox.appendChild(createOption(&#039;Bing&#039;, &#039;https://www.bing.com/search&#039;, &#039;q&#039;, &#039;q1&#039;, &#039;site:https://en.wikipedia.org&#039;));&lt;br /&gt;
    selectBox.appendChild(createOption(&#039;Wikiwix&#039;, &#039;https://www.wikiwix.com/&#039;, &#039;action&#039;, &#039;lang&#039;, &#039;en&#039;));&lt;br /&gt;
    selectBox.appendChild(createOption(&#039;Exalead&#039;, &#039;https://www.exalead.com/wikipedia/results&#039;, &#039;q&#039;, &#039;language&#039;, &#039;en&#039;));&lt;br /&gt;
    searchBox.style.marginLeft = &#039;0px&#039;;&lt;br /&gt;
    if (document.getElementById(&#039;loadStatus&#039;)) {&lt;br /&gt;
        var lStat = document.getElementById(&#039;loadStatus&#039;);&lt;br /&gt;
    } else {&lt;br /&gt;
        var lStat = searchForm.title;&lt;br /&gt;
        if( typeof lStat === &#039;object&#039;  &amp;amp;&amp;amp; typeof lStat.length === &#039;number&#039; ) lStat = lStat[0];&lt;br /&gt;
    }&lt;br /&gt;
    lStat.parentNode.insertBefore(selectBox, lStat);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
window.searchEngines = [];&lt;br /&gt;
&lt;br /&gt;
// Script is specific to Special:Search&lt;br /&gt;
if ( mw.config.get( &#039;wgCanonicalSpecialPageName&#039; ) === &#039;Search&#039;){&lt;br /&gt;
  $(SpecialSearchEnhanced);&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-select2.min.css&amp;diff=120487</id>
		<title>MediaWiki:Gadget-select2.min.css</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-select2.min.css&amp;diff=120487"/>
		<updated>2026-06-24T20:26:02Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: ←Created page with &amp;#039;/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ .select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-rig...&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */&lt;br /&gt;
.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{position:relative}.select2-container[dir=&amp;quot;rtl&amp;quot;] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;user-select:none;-webkit-user-select:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0 !important;clip:rect(0 0 0 0) !important;-webkit-clip-path:inset(50%) !important;clip-path:inset(50%) !important;height:1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important;white-space:nowrap !important}.select2-container--default .select2-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select2-container--default .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--default .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold}.select2-container--default .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--default .select2-selection--single .select2-selection__arrow{height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--default .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--default[dir=&amp;quot;rtl&amp;quot;] .select2-selection--single .select2-selection__clear{float:left}.select2-container--default[dir=&amp;quot;rtl&amp;quot;] .select2-selection--single .select2-selection__arrow{left:1px;right:auto}.select2-container--default.select2-container--disabled .select2-selection--single{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--default .select2-selection--multiple .select2-selection__rendered li{list-style:none}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-top:5px;margin-right:10px;padding:1px}.select2-container--default .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{color:#999;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:#333}.select2-container--default[dir=&amp;quot;rtl&amp;quot;] .select2-selection--multiple .select2-selection__choice,.select2-container--default[dir=&amp;quot;rtl&amp;quot;] .select2-selection--multiple .select2-search--inline{float:right}.select2-container--default[dir=&amp;quot;rtl&amp;quot;] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--default[dir=&amp;quot;rtl&amp;quot;] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--default.select2-container--focus .select2-selection--multiple{border:solid black 1px;outline:0}.select2-container--default.select2-container--disabled .select2-selection--multiple{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection__choice__remove{display:none}.select2-container--default.select2-container--open.select2-container--above .select2-selection--single,.select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple{border-top-left-radius:0;border-top-right-radius:0}.select2-container--default.select2-container--open.select2-container--below .select2-selection--single,.select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--default .select2-search--dropdown .select2-search__field{border:1px solid #aaa}.select2-container--default .select2-search--inline .select2-search__field{background:transparent;border:none;outline:0;box-shadow:none;-webkit-appearance:textfield}.select2-container--default .select2-results&amp;gt;.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--default .select2-results__option[role=group]{padding:0}.select2-container--default .select2-results__option[aria-disabled=true]{color:#999}.select2-container--default .select2-results__option[aria-selected=true]{background-color:#ddd}.select2-container--default .select2-results__option .select2-results__option{padding-left:1em}.select2-container--default .select2-results__option .select2-results__option .select2-results__group{padding-left:0}.select2-container--default .select2-results__option .select2-results__option .select2-results__option{margin-left:-1em;padding-left:2em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-2em;padding-left:3em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-3em;padding-left:4em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-4em;padding-left:5em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-5em;padding-left:6em}.select2-container--default .select2-results__option--highlighted[aria-selected]{background-color:#5897fb;color:white}.select2-container--default .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic .select2-selection--single{background-color:#f7f7f7;border:1px solid #aaa;border-radius:4px;outline:0;background-image:-webkit-linear-gradient(top, #fff 50%, #eee 100%);background-image:-o-linear-gradient(top, #fff 50%, #eee 100%);background-image:linear-gradient(to bottom, #fff 50%, #eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=&#039;#FFFFFFFF&#039;, endColorstr=&#039;#FFEEEEEE&#039;, GradientType=0)}.select2-container--classic .select2-selection--single:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--classic .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-right:10px}.select2-container--classic .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--classic .select2-selection--single .select2-selection__arrow{background-color:#ddd;border:none;border-left:1px solid #aaa;border-top-right-radius:4px;border-bottom-right-radius:4px;height:26px;position:absolute;top:1px;right:1px;width:20px;background-image:-webkit-linear-gradient(top, #eee 50%, #ccc 100%);background-image:-o-linear-gradient(top, #eee 50%, #ccc 100%);background-image:linear-gradient(to bottom, #eee 50%, #ccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=&#039;#FFEEEEEE&#039;, endColorstr=&#039;#FFCCCCCC&#039;, GradientType=0)}.select2-container--classic .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--classic[dir=&amp;quot;rtl&amp;quot;] .select2-selection--single .select2-selection__clear{float:left}.select2-container--classic[dir=&amp;quot;rtl&amp;quot;] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #aaa;border-radius:0;border-top-left-radius:4px;border-bottom-left-radius:4px;left:1px;right:auto}.select2-container--classic.select2-container--open .select2-selection--single{border:1px solid #5897fb}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0;background-image:-webkit-linear-gradient(top, #fff 0%, #eee 50%);background-image:-o-linear-gradient(top, #fff 0%, #eee 50%);background-image:linear-gradient(to bottom, #fff 0%, #eee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=&#039;#FFFFFFFF&#039;, endColorstr=&#039;#FFEEEEEE&#039;, GradientType=0)}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;background-image:-webkit-linear-gradient(top, #eee 50%, #fff 100%);background-image:-o-linear-gradient(top, #eee 50%, #fff 100%);background-image:linear-gradient(to bottom, #eee 50%, #fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=&#039;#FFEEEEEE&#039;, endColorstr=&#039;#FFFFFFFF&#039;, GradientType=0)}.select2-container--classic .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0}.select2-container--classic .select2-selection--multiple:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--classic .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove{color:#888;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover{color:#555}.select2-container--classic[dir=&amp;quot;rtl&amp;quot;] .select2-selection--multiple .select2-selection__choice{float:right;margin-left:5px;margin-right:auto}.select2-container--classic[dir=&amp;quot;rtl&amp;quot;] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--classic.select2-container--open .select2-selection--multiple{border:1px solid #5897fb}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--classic .select2-search--dropdown .select2-search__field{border:1px solid #aaa;outline:0}.select2-container--classic .select2-search--inline .select2-search__field{outline:0;box-shadow:none}.select2-container--classic .select2-dropdown{background-color:#fff;border:1px solid transparent}.select2-container--classic .select2-dropdown--above{border-bottom:none}.select2-container--classic .select2-dropdown--below{border-top:none}.select2-container--classic .select2-results&amp;gt;.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--classic .select2-results__option[role=group]{padding:0}.select2-container--classic .select2-results__option[aria-disabled=true]{color:grey}.select2-container--classic .select2-results__option--highlighted[aria-selected]{background-color:#3875d7;color:#fff}.select2-container--classic .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic.select2-container--open .select2-dropdown{border-color:#5897fb}&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-select2.min.js&amp;diff=120486</id>
		<title>MediaWiki:Gadget-select2.min.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-select2.min.js&amp;diff=120486"/>
		<updated>2026-06-24T20:25:31Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: ←Created page with &amp;#039;// &amp;lt;nowiki&amp;gt;  /*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(n){&amp;quot;function&amp;quot;==typeof define&amp;amp;&amp;amp;define.amd?define([&amp;quot;jquery&amp;quot;],n):/*&amp;quot;object&amp;quot;==typeof module&amp;amp;&amp;amp;module.exports?module.exports=function(e,t){return void 0===t&amp;amp;&amp;amp;(t=&amp;quot;undefined&amp;quot;!=typeof window?require(&amp;quot;jquery&amp;quot;):require(&amp;quot;jquery&amp;quot;)(e)),n(t),t}:*/n(jQuery)}(function(u){var e=function(){if(u&amp;amp;&amp;amp;u.fn&amp;amp;&amp;amp;u.fn.select2&amp;amp;&amp;amp;u.fn.select2.amd)var e=u.fn.select2.amd;var t,n,r,h,o,s,f,...&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// &amp;lt;nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */&lt;br /&gt;
!function(n){&amp;quot;function&amp;quot;==typeof define&amp;amp;&amp;amp;define.amd?define([&amp;quot;jquery&amp;quot;],n):/*&amp;quot;object&amp;quot;==typeof module&amp;amp;&amp;amp;module.exports?module.exports=function(e,t){return void 0===t&amp;amp;&amp;amp;(t=&amp;quot;undefined&amp;quot;!=typeof window?require(&amp;quot;jquery&amp;quot;):require(&amp;quot;jquery&amp;quot;)(e)),n(t),t}:*/n(jQuery)}(function(u){var e=function(){if(u&amp;amp;&amp;amp;u.fn&amp;amp;&amp;amp;u.fn.select2&amp;amp;&amp;amp;u.fn.select2.amd)var e=u.fn.select2.amd;var t,n,r,h,o,s,f,g,m,v,y,_,i,a,w;function b(e,t){return i.call(e,t)}function l(e,t){var n,r,i,o,s,a,l,c,u,d,p,h=t&amp;amp;&amp;amp;t.split(&amp;quot;/&amp;quot;),f=y.map,g=f&amp;amp;&amp;amp;f[&amp;quot;*&amp;quot;]||{};if(e){for(s=(e=e.split(&amp;quot;/&amp;quot;)).length-1,y.nodeIdCompat&amp;amp;&amp;amp;w.test(e[s])&amp;amp;&amp;amp;(e[s]=e[s].replace(w,&amp;quot;&amp;quot;)),&amp;quot;.&amp;quot;===e[0].charAt(0)&amp;amp;&amp;amp;h&amp;amp;&amp;amp;(e=h.slice(0,h.length-1).concat(e)),u=0;u&amp;lt;e.length;u++)if(&amp;quot;.&amp;quot;===(p=e[u]))e.splice(u,1),u-=1;else if(&amp;quot;..&amp;quot;===p){if(0===u||1===u&amp;amp;&amp;amp;&amp;quot;..&amp;quot;===e[2]||&amp;quot;..&amp;quot;===e[u-1])continue;0&amp;lt;u&amp;amp;&amp;amp;(e.splice(u-1,2),u-=2)}e=e.join(&amp;quot;/&amp;quot;)}if((h||g)&amp;amp;&amp;amp;f){for(u=(n=e.split(&amp;quot;/&amp;quot;)).length;0&amp;lt;u;u-=1){if(r=n.slice(0,u).join(&amp;quot;/&amp;quot;),h)for(d=h.length;0&amp;lt;d;d-=1)if(i=(i=f[h.slice(0,d).join(&amp;quot;/&amp;quot;)])&amp;amp;&amp;amp;i[r]){o=i,a=u;break}if(o)break;!l&amp;amp;&amp;amp;g&amp;amp;&amp;amp;g[r]&amp;amp;&amp;amp;(l=g[r],c=u)}!o&amp;amp;&amp;amp;l&amp;amp;&amp;amp;(o=l,a=c),o&amp;amp;&amp;amp;(n.splice(0,a,o),e=n.join(&amp;quot;/&amp;quot;))}return e}function A(t,n){return function(){var e=a.call(arguments,0);return&amp;quot;string&amp;quot;!=typeof e[0]&amp;amp;&amp;amp;1===e.length&amp;amp;&amp;amp;e.push(null),s.apply(h,e.concat([t,n]))}}function x(t){return function(e){m[t]=e}}function D(e){if(b(v,e)){var t=v[e];delete v[e],_[e]=!0,o.apply(h,t)}if(!b(m,e)&amp;amp;&amp;amp;!b(_,e))throw new Error(&amp;quot;No &amp;quot;+e);return m[e]}function c(e){var t,n=e?e.indexOf(&amp;quot;!&amp;quot;):-1;return-1&amp;lt;n&amp;amp;&amp;amp;(t=e.substring(0,n),e=e.substring(n+1,e.length)),[t,e]}function S(e){return e?c(e):[]}return e&amp;amp;&amp;amp;e.requirejs||(e?n=e:e={},m={},v={},y={},_={},i=Object.prototype.hasOwnProperty,a=[].slice,w=/\.js$/,f=function(e,t){var n,r=c(e),i=r[0],o=t[1];return e=r[1],i&amp;amp;&amp;amp;(n=D(i=l(i,o))),i?e=n&amp;amp;&amp;amp;n.normalize?n.normalize(e,function(t){return function(e){return l(e,t)}}(o)):l(e,o):(i=(r=c(e=l(e,o)))[0],e=r[1],i&amp;amp;&amp;amp;(n=D(i))),{f:i?i+&amp;quot;!&amp;quot;+e:e,n:e,pr:i,p:n}},g={require:function(e){return A(e)},exports:function(e){var t=m[e];return void 0!==t?t:m[e]={}},module:function(e){return{id:e,uri:&amp;quot;&amp;quot;,exports:m[e],config:function(e){return function(){return y&amp;amp;&amp;amp;y.config&amp;amp;&amp;amp;y.config[e]||{}}}(e)}}},o=function(e,t,n,r){var i,o,s,a,l,c,u,d=[],p=typeof n;if(c=S(r=r||e),&amp;quot;undefined&amp;quot;==p||&amp;quot;function&amp;quot;==p){for(t=!t.length&amp;amp;&amp;amp;n.length?[&amp;quot;require&amp;quot;,&amp;quot;exports&amp;quot;,&amp;quot;module&amp;quot;]:t,l=0;l&amp;lt;t.length;l+=1)if(&amp;quot;require&amp;quot;===(o=(a=f(t[l],c)).f))d[l]=g.require(e);else if(&amp;quot;exports&amp;quot;===o)d[l]=g.exports(e),u=!0;else if(&amp;quot;module&amp;quot;===o)i=d[l]=g.module(e);else if(b(m,o)||b(v,o)||b(_,o))d[l]=D(o);else{if(!a.p)throw new Error(e+&amp;quot; missing &amp;quot;+o);a.p.load(a.n,A(r,!0),x(o),{}),d[l]=m[o]}s=n?n.apply(m[e],d):void 0,e&amp;amp;&amp;amp;(i&amp;amp;&amp;amp;i.exports!==h&amp;amp;&amp;amp;i.exports!==m[e]?m[e]=i.exports:s===h&amp;amp;&amp;amp;u||(m[e]=s))}else e&amp;amp;&amp;amp;(m[e]=n)},t=n=s=function(e,t,n,r,i){if(&amp;quot;string&amp;quot;==typeof e)return g[e]?g[e](t):D(f(e,S(t)).f);if(!e.splice){if((y=e).deps&amp;amp;&amp;amp;s(y.deps,y.callback),!t)return;t.splice?(e=t,t=n,n=null):e=h}return t=t||function(){},&amp;quot;function&amp;quot;==typeof n&amp;amp;&amp;amp;(n=r,r=i),r?o(h,e,t,n):setTimeout(function(){o(h,e,t,n)},4),s},s.config=function(e){return s(e)},t._defined=m,(r=function(e,t,n){if(&amp;quot;string&amp;quot;!=typeof e)throw new Error(&amp;quot;See almond README: incorrect module build, no module name&amp;quot;);t.splice||(n=t,t=[]),b(m,e)||b(v,e)||(v[e]=[e,t,n])}).amd={jQuery:!0},e.requirejs=t,e.require=n,e.define=r),e.define(&amp;quot;almond&amp;quot;,function(){}),e.define(&amp;quot;jquery&amp;quot;,[],function(){var e=u||$;return null==e&amp;amp;&amp;amp;console&amp;amp;&amp;amp;console.error&amp;amp;&amp;amp;console.error(&amp;quot;Select2: An instance of jQuery or a jQuery-compatible library was not found. Make sure that you are including jQuery before Select2 on your web page.&amp;quot;),e}),e.define(&amp;quot;select2/utils&amp;quot;,[&amp;quot;jquery&amp;quot;],function(o){var i={};function u(e){var t=e.prototype,n=[];for(var r in t){&amp;quot;function&amp;quot;==typeof t[r]&amp;amp;&amp;amp;&amp;quot;constructor&amp;quot;!==r&amp;amp;&amp;amp;n.push(r)}return n}i.Extend=function(e,t){var n={}.hasOwnProperty;function r(){this.constructor=e}for(var i in t)n.call(t,i)&amp;amp;&amp;amp;(e[i]=t[i]);return r.prototype=t.prototype,e.prototype=new r,e.__super__=t.prototype,e},i.Decorate=function(r,i){var e=u(i),t=u(r);function o(){var e=Array.prototype.unshift,t=i.prototype.constructor.length,n=r.prototype.constructor;0&amp;lt;t&amp;amp;&amp;amp;(e.call(arguments,r.prototype.constructor),n=i.prototype.constructor),n.apply(this,arguments)}i.displayName=r.displayName,o.prototype=new function(){this.constructor=o};for(var n=0;n&amp;lt;t.length;n++){var s=t[n];o.prototype[s]=r.prototype[s]}function a(e){var t=function(){};e in o.prototype&amp;amp;&amp;amp;(t=o.prototype[e]);var n=i.prototype[e];return function(){return Array.prototype.unshift.call(arguments,t),n.apply(this,arguments)}}for(var l=0;l&amp;lt;e.length;l++){var c=e[l];o.prototype[c]=a(c)}return o};function e(){this.listeners={}}e.prototype.on=function(e,t){this.listeners=this.listeners||{},e in this.listeners?this.listeners[e].push(t):this.listeners[e]=[t]},e.prototype.trigger=function(e){var t=Array.prototype.slice,n=t.call(arguments,1);this.listeners=this.listeners||{},null==n&amp;amp;&amp;amp;(n=[]),0===n.length&amp;amp;&amp;amp;n.push({}),(n[0]._type=e)in this.listeners&amp;amp;&amp;amp;this.invoke(this.listeners[e],t.call(arguments,1)),&amp;quot;*&amp;quot;in this.listeners&amp;amp;&amp;amp;this.invoke(this.listeners[&amp;quot;*&amp;quot;],arguments)},e.prototype.invoke=function(e,t){for(var n=0,r=e.length;n&amp;lt;r;n++)e[n].apply(this,t)},i.Observable=e,i.generateChars=function(e){for(var t=&amp;quot;&amp;quot;,n=0;n&amp;lt;e;n++){t+=Math.floor(36*Math.random()).toString(36)}return t},i.bind=function(e,t){return function(){e.apply(t,arguments)}},i._convertData=function(e){for(var t in e){var n=t.split(&amp;quot;-&amp;quot;),r=e;if(1!==n.length){for(var i=0;i&amp;lt;n.length;i++){var o=n[i];(o=o.substring(0,1).toLowerCase()+o.substring(1))in r||(r[o]={}),i==n.length-1&amp;amp;&amp;amp;(r[o]=e[t]),r=r[o]}delete e[t]}}return e},i.hasScroll=function(e,t){var n=o(t),r=t.style.overflowX,i=t.style.overflowY;return(r!==i||&amp;quot;hidden&amp;quot;!==i&amp;amp;&amp;amp;&amp;quot;visible&amp;quot;!==i)&amp;amp;&amp;amp;(&amp;quot;scroll&amp;quot;===r||&amp;quot;scroll&amp;quot;===i||(n.innerHeight()&amp;lt;t.scrollHeight||n.innerWidth()&amp;lt;t.scrollWidth))},i.escapeMarkup=function(e){var t={&amp;quot;\\&amp;quot;:&amp;quot;&amp;amp;#92;&amp;quot;,&amp;quot;&amp;amp;&amp;quot;:&amp;quot;&amp;amp;amp;&amp;quot;,&amp;quot;&amp;lt;&amp;quot;:&amp;quot;&amp;amp;lt;&amp;quot;,&amp;quot;&amp;gt;&amp;quot;:&amp;quot;&amp;amp;gt;&amp;quot;,&#039;&amp;quot;&#039;:&amp;quot;&amp;amp;quot;&amp;quot;,&amp;quot;&#039;&amp;quot;:&amp;quot;&amp;amp;#39;&amp;quot;,&amp;quot;/&amp;quot;:&amp;quot;&amp;amp;#47;&amp;quot;};return&amp;quot;string&amp;quot;!=typeof e?e:String(e).replace(/[&amp;amp;&amp;lt;&amp;gt;&amp;quot;&#039;\/\\]/g,function(e){return t[e]})},i.appendMany=function(e,t){if(&amp;quot;1.7&amp;quot;===o.fn.jquery.substr(0,3)){var n=o();o.map(t,function(e){n=n.add(e)}),t=n}e.append(t)},i.__cache={};var n=0;return i.GetUniqueElementId=function(e){var t=e.getAttribute(&amp;quot;data-select2-id&amp;quot;);return null==t&amp;amp;&amp;amp;(e.id?(t=e.id,e.setAttribute(&amp;quot;data-select2-id&amp;quot;,t)):(e.setAttribute(&amp;quot;data-select2-id&amp;quot;,++n),t=n.toString())),t},i.StoreData=function(e,t,n){var r=i.GetUniqueElementId(e);i.__cache[r]||(i.__cache[r]={}),i.__cache[r][t]=n},i.GetData=function(e,t){var n=i.GetUniqueElementId(e);return t?i.__cache[n]&amp;amp;&amp;amp;null!=i.__cache[n][t]?i.__cache[n][t]:o(e).data(t):i.__cache[n]},i.RemoveData=function(e){var t=i.GetUniqueElementId(e);null!=i.__cache[t]&amp;amp;&amp;amp;delete i.__cache[t],e.removeAttribute(&amp;quot;data-select2-id&amp;quot;)},i}),e.define(&amp;quot;select2/results&amp;quot;,[&amp;quot;jquery&amp;quot;,&amp;quot;./utils&amp;quot;],function(h,f){function r(e,t,n){this.$element=e,this.data=n,this.options=t,r.__super__.constructor.call(this)}return f.Extend(r,f.Observable),r.prototype.render=function(){var e=h(&#039;&amp;lt;ul class=&amp;quot;select2-results__options&amp;quot; role=&amp;quot;listbox&amp;quot;&amp;gt;&amp;lt;/ul&amp;gt;&#039;);return this.options.get(&amp;quot;multiple&amp;quot;)&amp;amp;&amp;amp;e.attr(&amp;quot;aria-multiselectable&amp;quot;,&amp;quot;true&amp;quot;),this.$results=e},r.prototype.clear=function(){this.$results.empty()},r.prototype.displayMessage=function(e){var t=this.options.get(&amp;quot;escapeMarkup&amp;quot;);this.clear(),this.hideLoading();var n=h(&#039;&amp;lt;li role=&amp;quot;alert&amp;quot; aria-live=&amp;quot;assertive&amp;quot; class=&amp;quot;select2-results__option&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;&#039;),r=this.options.get(&amp;quot;translations&amp;quot;).get(e.message);n.append(t(r(e.args))),n[0].className+=&amp;quot; select2-results__message&amp;quot;,this.$results.append(n)},r.prototype.hideMessages=function(){this.$results.find(&amp;quot;.select2-results__message&amp;quot;).remove()},r.prototype.append=function(e){this.hideLoading();var t=[];if(null!=e.results&amp;amp;&amp;amp;0!==e.results.length){e.results=this.sort(e.results);for(var n=0;n&amp;lt;e.results.length;n++){var r=e.results[n],i=this.option(r);t.push(i)}this.$results.append(t)}else 0===this.$results.children().length&amp;amp;&amp;amp;this.trigger(&amp;quot;results:message&amp;quot;,{message:&amp;quot;noResults&amp;quot;})},r.prototype.position=function(e,t){t.find(&amp;quot;.select2-results&amp;quot;).append(e)},r.prototype.sort=function(e){return this.options.get(&amp;quot;sorter&amp;quot;)(e)},r.prototype.highlightFirstItem=function(){var e=this.$results.find(&amp;quot;.select2-results__option[aria-selected]&amp;quot;),t=e.filter(&amp;quot;[aria-selected=true]&amp;quot;);0&amp;lt;t.length?t.first().trigger(&amp;quot;mouseenter&amp;quot;):e.first().trigger(&amp;quot;mouseenter&amp;quot;),this.ensureHighlightVisible()},r.prototype.setClasses=function(){var t=this;this.data.current(function(e){var r=h.map(e,function(e){return e.id.toString()});t.$results.find(&amp;quot;.select2-results__option[aria-selected]&amp;quot;).each(function(){var e=h(this),t=f.GetData(this,&amp;quot;data&amp;quot;),n=&amp;quot;&amp;quot;+t.id;null!=t.element&amp;amp;&amp;amp;t.element.selected||null==t.element&amp;amp;&amp;amp;-1&amp;lt;h.inArray(n,r)?e.attr(&amp;quot;aria-selected&amp;quot;,&amp;quot;true&amp;quot;):e.attr(&amp;quot;aria-selected&amp;quot;,&amp;quot;false&amp;quot;)})})},r.prototype.showLoading=function(e){this.hideLoading();var t={disabled:!0,loading:!0,text:this.options.get(&amp;quot;translations&amp;quot;).get(&amp;quot;searching&amp;quot;)(e)},n=this.option(t);n.className+=&amp;quot; loading-results&amp;quot;,this.$results.prepend(n)},r.prototype.hideLoading=function(){this.$results.find(&amp;quot;.loading-results&amp;quot;).remove()},r.prototype.option=function(e){var t=document.createElement(&amp;quot;li&amp;quot;);t.className=&amp;quot;select2-results__option&amp;quot;;var n={role:&amp;quot;option&amp;quot;,&amp;quot;aria-selected&amp;quot;:&amp;quot;false&amp;quot;},r=window.Element.prototype.matches||window.Element.prototype.msMatchesSelector||window.Element.prototype.webkitMatchesSelector;for(var i in(null!=e.element&amp;amp;&amp;amp;r.call(e.element,&amp;quot;:disabled&amp;quot;)||null==e.element&amp;amp;&amp;amp;e.disabled)&amp;amp;&amp;amp;(delete n[&amp;quot;aria-selected&amp;quot;],n[&amp;quot;aria-disabled&amp;quot;]=&amp;quot;true&amp;quot;),null==e.id&amp;amp;&amp;amp;delete n[&amp;quot;aria-selected&amp;quot;],null!=e._resultId&amp;amp;&amp;amp;(t.id=e._resultId),e.title&amp;amp;&amp;amp;(t.title=e.title),e.children&amp;amp;&amp;amp;(n.role=&amp;quot;group&amp;quot;,n[&amp;quot;aria-label&amp;quot;]=e.text,delete n[&amp;quot;aria-selected&amp;quot;]),n){var o=n[i];t.setAttribute(i,o)}if(e.children){var s=h(t),a=document.createElement(&amp;quot;strong&amp;quot;);a.className=&amp;quot;select2-results__group&amp;quot;;h(a);this.template(e,a);for(var l=[],c=0;c&amp;lt;e.children.length;c++){var u=e.children[c],d=this.option(u);l.push(d)}var p=h(&amp;quot;&amp;lt;ul&amp;gt;&amp;lt;/ul&amp;gt;&amp;quot;,{class:&amp;quot;select2-results__options select2-results__options--nested&amp;quot;});p.append(l),s.append(a),s.append(p)}else this.template(e,t);return f.StoreData(t,&amp;quot;data&amp;quot;,e),t},r.prototype.bind=function(t,e){var l=this,n=t.id+&amp;quot;-results&amp;quot;;this.$results.attr(&amp;quot;id&amp;quot;,n),t.on(&amp;quot;results:all&amp;quot;,function(e){l.clear(),l.append(e.data),t.isOpen()&amp;amp;&amp;amp;(l.setClasses(),l.highlightFirstItem())}),t.on(&amp;quot;results:append&amp;quot;,function(e){l.append(e.data),t.isOpen()&amp;amp;&amp;amp;l.setClasses()}),t.on(&amp;quot;query&amp;quot;,function(e){l.hideMessages(),l.showLoading(e)}),t.on(&amp;quot;select&amp;quot;,function(){t.isOpen()&amp;amp;&amp;amp;(l.setClasses(),l.options.get(&amp;quot;scrollAfterSelect&amp;quot;)&amp;amp;&amp;amp;l.highlightFirstItem())}),t.on(&amp;quot;unselect&amp;quot;,function(){t.isOpen()&amp;amp;&amp;amp;(l.setClasses(),l.options.get(&amp;quot;scrollAfterSelect&amp;quot;)&amp;amp;&amp;amp;l.highlightFirstItem())}),t.on(&amp;quot;open&amp;quot;,function(){l.$results.attr(&amp;quot;aria-expanded&amp;quot;,&amp;quot;true&amp;quot;),l.$results.attr(&amp;quot;aria-hidden&amp;quot;,&amp;quot;false&amp;quot;),l.setClasses(),l.ensureHighlightVisible()}),t.on(&amp;quot;close&amp;quot;,function(){l.$results.attr(&amp;quot;aria-expanded&amp;quot;,&amp;quot;false&amp;quot;),l.$results.attr(&amp;quot;aria-hidden&amp;quot;,&amp;quot;true&amp;quot;),l.$results.removeAttr(&amp;quot;aria-activedescendant&amp;quot;)}),t.on(&amp;quot;results:toggle&amp;quot;,function(){var e=l.getHighlightedResults();0!==e.length&amp;amp;&amp;amp;e.trigger(&amp;quot;mouseup&amp;quot;)}),t.on(&amp;quot;results:select&amp;quot;,function(){var e=l.getHighlightedResults();if(0!==e.length){var t=f.GetData(e[0],&amp;quot;data&amp;quot;);&amp;quot;true&amp;quot;==e.attr(&amp;quot;aria-selected&amp;quot;)?l.trigger(&amp;quot;close&amp;quot;,{}):l.trigger(&amp;quot;select&amp;quot;,{data:t})}}),t.on(&amp;quot;results:previous&amp;quot;,function(){var e=l.getHighlightedResults(),t=l.$results.find(&amp;quot;[aria-selected]&amp;quot;),n=t.index(e);if(!(n&amp;lt;=0)){var r=n-1;0===e.length&amp;amp;&amp;amp;(r=0);var i=t.eq(r);i.trigger(&amp;quot;mouseenter&amp;quot;);var o=l.$results.offset().top,s=i.offset().top,a=l.$results.scrollTop()+(s-o);0===r?l.$results.scrollTop(0):s-o&amp;lt;0&amp;amp;&amp;amp;l.$results.scrollTop(a)}}),t.on(&amp;quot;results:next&amp;quot;,function(){var e=l.getHighlightedResults(),t=l.$results.find(&amp;quot;[aria-selected]&amp;quot;),n=t.index(e)+1;if(!(n&amp;gt;=t.length)){var r=t.eq(n);r.trigger(&amp;quot;mouseenter&amp;quot;);var i=l.$results.offset().top+l.$results.outerHeight(!1),o=r.offset().top+r.outerHeight(!1),s=l.$results.scrollTop()+o-i;0===n?l.$results.scrollTop(0):i&amp;lt;o&amp;amp;&amp;amp;l.$results.scrollTop(s)}}),t.on(&amp;quot;results:focus&amp;quot;,function(e){e.element.addClass(&amp;quot;select2-results__option--highlighted&amp;quot;)}),t.on(&amp;quot;results:message&amp;quot;,function(e){l.displayMessage(e)}),h.fn.mousewheel&amp;amp;&amp;amp;this.$results.on(&amp;quot;mousewheel&amp;quot;,function(e){var t=l.$results.scrollTop(),n=l.$results.get(0).scrollHeight-t+e.deltaY,r=0&amp;lt;e.deltaY&amp;amp;&amp;amp;t-e.deltaY&amp;lt;=0,i=e.deltaY&amp;lt;0&amp;amp;&amp;amp;n&amp;lt;=l.$results.height();r?(l.$results.scrollTop(0),e.preventDefault(),e.stopPropagation()):i&amp;amp;&amp;amp;(l.$results.scrollTop(l.$results.get(0).scrollHeight-l.$results.height()),e.preventDefault(),e.stopPropagation())}),this.$results.on(&amp;quot;mouseup&amp;quot;,&amp;quot;.select2-results__option[aria-selected]&amp;quot;,function(e){var t=h(this),n=f.GetData(this,&amp;quot;data&amp;quot;);&amp;quot;true&amp;quot;!==t.attr(&amp;quot;aria-selected&amp;quot;)?l.trigger(&amp;quot;select&amp;quot;,{originalEvent:e,data:n}):l.options.get(&amp;quot;multiple&amp;quot;)?l.trigger(&amp;quot;unselect&amp;quot;,{originalEvent:e,data:n}):l.trigger(&amp;quot;close&amp;quot;,{})}),this.$results.on(&amp;quot;mouseenter&amp;quot;,&amp;quot;.select2-results__option[aria-selected]&amp;quot;,function(e){var t=f.GetData(this,&amp;quot;data&amp;quot;);l.getHighlightedResults().removeClass(&amp;quot;select2-results__option--highlighted&amp;quot;),l.trigger(&amp;quot;results:focus&amp;quot;,{data:t,element:h(this)})})},r.prototype.getHighlightedResults=function(){return this.$results.find(&amp;quot;.select2-results__option--highlighted&amp;quot;)},r.prototype.destroy=function(){this.$results.remove()},r.prototype.ensureHighlightVisible=function(){var e=this.getHighlightedResults();if(0!==e.length){var t=this.$results.find(&amp;quot;[aria-selected]&amp;quot;).index(e),n=this.$results.offset().top,r=e.offset().top,i=this.$results.scrollTop()+(r-n),o=r-n;i-=2*e.outerHeight(!1),t&amp;lt;=2?this.$results.scrollTop(0):(o&amp;gt;this.$results.outerHeight()||o&amp;lt;0)&amp;amp;&amp;amp;this.$results.scrollTop(i)}},r.prototype.template=function(e,t){var n=this.options.get(&amp;quot;templateResult&amp;quot;),r=this.options.get(&amp;quot;escapeMarkup&amp;quot;),i=n(e,t);null==i?t.style.display=&amp;quot;none&amp;quot;:&amp;quot;string&amp;quot;==typeof i?t.innerHTML=r(i):h(t).append(i)},r}),e.define(&amp;quot;select2/keys&amp;quot;,[],function(){return{BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,DELETE:46}}),e.define(&amp;quot;select2/selection/base&amp;quot;,[&amp;quot;jquery&amp;quot;,&amp;quot;../utils&amp;quot;,&amp;quot;../keys&amp;quot;],function(n,r,i){function o(e,t){this.$element=e,this.options=t,o.__super__.constructor.call(this)}return r.Extend(o,r.Observable),o.prototype.render=function(){var e=n(&#039;&amp;lt;span class=&amp;quot;select2-selection&amp;quot; role=&amp;quot;combobox&amp;quot;  aria-haspopup=&amp;quot;true&amp;quot; aria-expanded=&amp;quot;false&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;);return this._tabindex=0,null!=r.GetData(this.$element[0],&amp;quot;old-tabindex&amp;quot;)?this._tabindex=r.GetData(this.$element[0],&amp;quot;old-tabindex&amp;quot;):null!=this.$element.attr(&amp;quot;tabindex&amp;quot;)&amp;amp;&amp;amp;(this._tabindex=this.$element.attr(&amp;quot;tabindex&amp;quot;)),e.attr(&amp;quot;title&amp;quot;,this.$element.attr(&amp;quot;title&amp;quot;)),e.attr(&amp;quot;tabindex&amp;quot;,this._tabindex),e.attr(&amp;quot;aria-disabled&amp;quot;,&amp;quot;false&amp;quot;),this.$selection=e},o.prototype.bind=function(e,t){var n=this,r=e.id+&amp;quot;-results&amp;quot;;this.container=e,this.$selection.on(&amp;quot;focus&amp;quot;,function(e){n.trigger(&amp;quot;focus&amp;quot;,e)}),this.$selection.on(&amp;quot;blur&amp;quot;,function(e){n._handleBlur(e)}),this.$selection.on(&amp;quot;keydown&amp;quot;,function(e){n.trigger(&amp;quot;keypress&amp;quot;,e),e.which===i.SPACE&amp;amp;&amp;amp;e.preventDefault()}),e.on(&amp;quot;results:focus&amp;quot;,function(e){n.$selection.attr(&amp;quot;aria-activedescendant&amp;quot;,e.data._resultId)}),e.on(&amp;quot;selection:update&amp;quot;,function(e){n.update(e.data)}),e.on(&amp;quot;open&amp;quot;,function(){n.$selection.attr(&amp;quot;aria-expanded&amp;quot;,&amp;quot;true&amp;quot;),n.$selection.attr(&amp;quot;aria-owns&amp;quot;,r),n._attachCloseHandler(e)}),e.on(&amp;quot;close&amp;quot;,function(){n.$selection.attr(&amp;quot;aria-expanded&amp;quot;,&amp;quot;false&amp;quot;),n.$selection.removeAttr(&amp;quot;aria-activedescendant&amp;quot;),n.$selection.removeAttr(&amp;quot;aria-owns&amp;quot;),n.$selection.trigger(&amp;quot;focus&amp;quot;),n._detachCloseHandler(e)}),e.on(&amp;quot;enable&amp;quot;,function(){n.$selection.attr(&amp;quot;tabindex&amp;quot;,n._tabindex),n.$selection.attr(&amp;quot;aria-disabled&amp;quot;,&amp;quot;false&amp;quot;)}),e.on(&amp;quot;disable&amp;quot;,function(){n.$selection.attr(&amp;quot;tabindex&amp;quot;,&amp;quot;-1&amp;quot;),n.$selection.attr(&amp;quot;aria-disabled&amp;quot;,&amp;quot;true&amp;quot;)})},o.prototype._handleBlur=function(e){var t=this;window.setTimeout(function(){document.activeElement==t.$selection[0]||n.contains(t.$selection[0],document.activeElement)||t.trigger(&amp;quot;blur&amp;quot;,e)},1)},o.prototype._attachCloseHandler=function(e){n(document.body).on(&amp;quot;mousedown.select2.&amp;quot;+e.id,function(e){var t=n(e.target).closest(&amp;quot;.select2&amp;quot;);n(&amp;quot;.select2.select2-container--open&amp;quot;).each(function(){this!=t[0]&amp;amp;&amp;amp;r.GetData(this,&amp;quot;element&amp;quot;).select2(&amp;quot;close&amp;quot;)})})},o.prototype._detachCloseHandler=function(e){n(document.body).off(&amp;quot;mousedown.select2.&amp;quot;+e.id)},o.prototype.position=function(e,t){t.find(&amp;quot;.selection&amp;quot;).append(e)},o.prototype.destroy=function(){this._detachCloseHandler(this.container)},o.prototype.update=function(e){throw new Error(&amp;quot;The `update` method must be defined in child classes.&amp;quot;)},o}),e.define(&amp;quot;select2/selection/single&amp;quot;,[&amp;quot;jquery&amp;quot;,&amp;quot;./base&amp;quot;,&amp;quot;../utils&amp;quot;,&amp;quot;../keys&amp;quot;],function(e,t,n,r){function i(){i.__super__.constructor.apply(this,arguments)}return n.Extend(i,t),i.prototype.render=function(){var e=i.__super__.render.call(this);return e.addClass(&amp;quot;select2-selection--single&amp;quot;),e.html(&#039;&amp;lt;span class=&amp;quot;select2-selection__rendered&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;select2-selection__arrow&amp;quot; role=&amp;quot;presentation&amp;quot;&amp;gt;&amp;lt;b role=&amp;quot;presentation&amp;quot;&amp;gt;&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;&#039;),e},i.prototype.bind=function(t,e){var n=this;i.__super__.bind.apply(this,arguments);var r=t.id+&amp;quot;-container&amp;quot;;this.$selection.find(&amp;quot;.select2-selection__rendered&amp;quot;).attr(&amp;quot;id&amp;quot;,r).attr(&amp;quot;role&amp;quot;,&amp;quot;textbox&amp;quot;).attr(&amp;quot;aria-readonly&amp;quot;,&amp;quot;true&amp;quot;),this.$selection.attr(&amp;quot;aria-labelledby&amp;quot;,r),this.$selection.on(&amp;quot;mousedown&amp;quot;,function(e){1===e.which&amp;amp;&amp;amp;n.trigger(&amp;quot;toggle&amp;quot;,{originalEvent:e})}),this.$selection.on(&amp;quot;focus&amp;quot;,function(e){}),this.$selection.on(&amp;quot;blur&amp;quot;,function(e){}),t.on(&amp;quot;focus&amp;quot;,function(e){t.isOpen()||n.$selection.trigger(&amp;quot;focus&amp;quot;)})},i.prototype.clear=function(){var e=this.$selection.find(&amp;quot;.select2-selection__rendered&amp;quot;);e.empty(),e.removeAttr(&amp;quot;title&amp;quot;)},i.prototype.display=function(e,t){var n=this.options.get(&amp;quot;templateSelection&amp;quot;);return this.options.get(&amp;quot;escapeMarkup&amp;quot;)(n(e,t))},i.prototype.selectionContainer=function(){return e(&amp;quot;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;)},i.prototype.update=function(e){if(0!==e.length){var t=e[0],n=this.$selection.find(&amp;quot;.select2-selection__rendered&amp;quot;),r=this.display(t,n);n.empty().append(r);var i=t.title||t.text;i?n.attr(&amp;quot;title&amp;quot;,i):n.removeAttr(&amp;quot;title&amp;quot;)}else this.clear()},i}),e.define(&amp;quot;select2/selection/multiple&amp;quot;,[&amp;quot;jquery&amp;quot;,&amp;quot;./base&amp;quot;,&amp;quot;../utils&amp;quot;],function(i,e,l){function n(e,t){n.__super__.constructor.apply(this,arguments)}return l.Extend(n,e),n.prototype.render=function(){var e=n.__super__.render.call(this);return e.addClass(&amp;quot;select2-selection--multiple&amp;quot;),e.html(&#039;&amp;lt;ul class=&amp;quot;select2-selection__rendered&amp;quot;&amp;gt;&amp;lt;/ul&amp;gt;&#039;),e},n.prototype.bind=function(e,t){var r=this;n.__super__.bind.apply(this,arguments),this.$selection.on(&amp;quot;click&amp;quot;,function(e){r.trigger(&amp;quot;toggle&amp;quot;,{originalEvent:e})}),this.$selection.on(&amp;quot;click&amp;quot;,&amp;quot;.select2-selection__choice__remove&amp;quot;,function(e){if(!r.options.get(&amp;quot;disabled&amp;quot;)){var t=i(this).parent(),n=l.GetData(t[0],&amp;quot;data&amp;quot;);r.trigger(&amp;quot;unselect&amp;quot;,{originalEvent:e,data:n})}})},n.prototype.clear=function(){var e=this.$selection.find(&amp;quot;.select2-selection__rendered&amp;quot;);e.empty(),e.removeAttr(&amp;quot;title&amp;quot;)},n.prototype.display=function(e,t){var n=this.options.get(&amp;quot;templateSelection&amp;quot;);return this.options.get(&amp;quot;escapeMarkup&amp;quot;)(n(e,t))},n.prototype.selectionContainer=function(){return i(&#039;&amp;lt;li class=&amp;quot;select2-selection__choice&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;select2-selection__choice__remove&amp;quot; role=&amp;quot;presentation&amp;quot;&amp;gt;&amp;amp;times;&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;&#039;)},n.prototype.update=function(e){if(this.clear(),0!==e.length){for(var t=[],n=0;n&amp;lt;e.length;n++){var r=e[n],i=this.selectionContainer(),o=this.display(r,i);i.append(o);var s=r.title||r.text;s&amp;amp;&amp;amp;i.attr(&amp;quot;title&amp;quot;,s),l.StoreData(i[0],&amp;quot;data&amp;quot;,r),t.push(i)}var a=this.$selection.find(&amp;quot;.select2-selection__rendered&amp;quot;);l.appendMany(a,t)}},n}),e.define(&amp;quot;select2/selection/placeholder&amp;quot;,[&amp;quot;../utils&amp;quot;],function(e){function t(e,t,n){this.placeholder=this.normalizePlaceholder(n.get(&amp;quot;placeholder&amp;quot;)),e.call(this,t,n)}return t.prototype.normalizePlaceholder=function(e,t){return&amp;quot;string&amp;quot;==typeof t&amp;amp;&amp;amp;(t={id:&amp;quot;&amp;quot;,text:t}),t},t.prototype.createPlaceholder=function(e,t){var n=this.selectionContainer();return n.html(this.display(t)),n.addClass(&amp;quot;select2-selection__placeholder&amp;quot;).removeClass(&amp;quot;select2-selection__choice&amp;quot;),n},t.prototype.update=function(e,t){var n=1==t.length&amp;amp;&amp;amp;t[0].id!=this.placeholder.id;if(1&amp;lt;t.length||n)return e.call(this,t);this.clear();var r=this.createPlaceholder(this.placeholder);this.$selection.find(&amp;quot;.select2-selection__rendered&amp;quot;).append(r)},t}),e.define(&amp;quot;select2/selection/allowClear&amp;quot;,[&amp;quot;jquery&amp;quot;,&amp;quot;../keys&amp;quot;,&amp;quot;../utils&amp;quot;],function(i,r,a){function e(){}return e.prototype.bind=function(e,t,n){var r=this;e.call(this,t,n),null==this.placeholder&amp;amp;&amp;amp;this.options.get(&amp;quot;debug&amp;quot;)&amp;amp;&amp;amp;window.console&amp;amp;&amp;amp;console.error&amp;amp;&amp;amp;console.error(&amp;quot;Select2: The `allowClear` option should be used in combination with the `placeholder` option.&amp;quot;),this.$selection.on(&amp;quot;mousedown&amp;quot;,&amp;quot;.select2-selection__clear&amp;quot;,function(e){r._handleClear(e)}),t.on(&amp;quot;keypress&amp;quot;,function(e){r._handleKeyboardClear(e,t)})},e.prototype._handleClear=function(e,t){if(!this.options.get(&amp;quot;disabled&amp;quot;)){var n=this.$selection.find(&amp;quot;.select2-selection__clear&amp;quot;);if(0!==n.length){t.stopPropagation();var r=a.GetData(n[0],&amp;quot;data&amp;quot;),i=this.$element.val();this.$element.val(this.placeholder.id);var o={data:r};if(this.trigger(&amp;quot;clear&amp;quot;,o),o.prevented)this.$element.val(i);else{for(var s=0;s&amp;lt;r.length;s++)if(o={data:r[s]},this.trigger(&amp;quot;unselect&amp;quot;,o),o.prevented)return void this.$element.val(i);this.$element.trigger(&amp;quot;change&amp;quot;),this.trigger(&amp;quot;toggle&amp;quot;,{})}}}},e.prototype._handleKeyboardClear=function(e,t,n){n.isOpen()||t.which!=r.DELETE&amp;amp;&amp;amp;t.which!=r.BACKSPACE||this._handleClear(t)},e.prototype.update=function(e,t){if(e.call(this,t),!(0&amp;lt;this.$selection.find(&amp;quot;.select2-selection__placeholder&amp;quot;).length||0===t.length)){var n=this.options.get(&amp;quot;translations&amp;quot;).get(&amp;quot;removeAllItems&amp;quot;),r=i(&#039;&amp;lt;span class=&amp;quot;select2-selection__clear&amp;quot; title=&amp;quot;&#039;+n()+&#039;&amp;quot;&amp;gt;&amp;amp;times;&amp;lt;/span&amp;gt;&#039;);a.StoreData(r[0],&amp;quot;data&amp;quot;,t),this.$selection.find(&amp;quot;.select2-selection__rendered&amp;quot;).prepend(r)}},e}),e.define(&amp;quot;select2/selection/search&amp;quot;,[&amp;quot;jquery&amp;quot;,&amp;quot;../utils&amp;quot;,&amp;quot;../keys&amp;quot;],function(r,a,l){function e(e,t,n){e.call(this,t,n)}return e.prototype.render=function(e){var t=r(&#039;&amp;lt;li class=&amp;quot;select2-search select2-search--inline&amp;quot;&amp;gt;&amp;lt;input class=&amp;quot;select2-search__field&amp;quot; type=&amp;quot;search&amp;quot; tabindex=&amp;quot;-1&amp;quot; autocomplete=&amp;quot;off&amp;quot; autocorrect=&amp;quot;off&amp;quot; autocapitalize=&amp;quot;none&amp;quot; spellcheck=&amp;quot;false&amp;quot; role=&amp;quot;searchbox&amp;quot; aria-autocomplete=&amp;quot;list&amp;quot; /&amp;gt;&amp;lt;/li&amp;gt;&#039;);this.$searchContainer=t,this.$search=t.find(&amp;quot;input&amp;quot;);var n=e.call(this);return this._transferTabIndex(),n},e.prototype.bind=function(e,t,n){var r=this,i=t.id+&amp;quot;-results&amp;quot;;e.call(this,t,n),t.on(&amp;quot;open&amp;quot;,function(){r.$search.attr(&amp;quot;aria-controls&amp;quot;,i),r.$search.trigger(&amp;quot;focus&amp;quot;)}),t.on(&amp;quot;close&amp;quot;,function(){r.$search.val(&amp;quot;&amp;quot;),r.$search.removeAttr(&amp;quot;aria-controls&amp;quot;),r.$search.removeAttr(&amp;quot;aria-activedescendant&amp;quot;),r.$search.trigger(&amp;quot;focus&amp;quot;)}),t.on(&amp;quot;enable&amp;quot;,function(){r.$search.prop(&amp;quot;disabled&amp;quot;,!1),r._transferTabIndex()}),t.on(&amp;quot;disable&amp;quot;,function(){r.$search.prop(&amp;quot;disabled&amp;quot;,!0)}),t.on(&amp;quot;focus&amp;quot;,function(e){r.$search.trigger(&amp;quot;focus&amp;quot;)}),t.on(&amp;quot;results:focus&amp;quot;,function(e){e.data._resultId?r.$search.attr(&amp;quot;aria-activedescendant&amp;quot;,e.data._resultId):r.$search.removeAttr(&amp;quot;aria-activedescendant&amp;quot;)}),this.$selection.on(&amp;quot;focusin&amp;quot;,&amp;quot;.select2-search--inline&amp;quot;,function(e){r.trigger(&amp;quot;focus&amp;quot;,e)}),this.$selection.on(&amp;quot;focusout&amp;quot;,&amp;quot;.select2-search--inline&amp;quot;,function(e){r._handleBlur(e)}),this.$selection.on(&amp;quot;keydown&amp;quot;,&amp;quot;.select2-search--inline&amp;quot;,function(e){if(e.stopPropagation(),r.trigger(&amp;quot;keypress&amp;quot;,e),r._keyUpPrevented=e.isDefaultPrevented(),e.which===l.BACKSPACE&amp;amp;&amp;amp;&amp;quot;&amp;quot;===r.$search.val()){var t=r.$searchContainer.prev(&amp;quot;.select2-selection__choice&amp;quot;);if(0&amp;lt;t.length){var n=a.GetData(t[0],&amp;quot;data&amp;quot;);r.searchRemoveChoice(n),e.preventDefault()}}}),this.$selection.on(&amp;quot;click&amp;quot;,&amp;quot;.select2-search--inline&amp;quot;,function(e){r.$search.val()&amp;amp;&amp;amp;e.stopPropagation()});var o=document.documentMode,s=o&amp;amp;&amp;amp;o&amp;lt;=11;this.$selection.on(&amp;quot;input.searchcheck&amp;quot;,&amp;quot;.select2-search--inline&amp;quot;,function(e){s?r.$selection.off(&amp;quot;input.search input.searchcheck&amp;quot;):r.$selection.off(&amp;quot;keyup.search&amp;quot;)}),this.$selection.on(&amp;quot;keyup.search input.search&amp;quot;,&amp;quot;.select2-search--inline&amp;quot;,function(e){if(s&amp;amp;&amp;amp;&amp;quot;input&amp;quot;===e.type)r.$selection.off(&amp;quot;input.search input.searchcheck&amp;quot;);else{var t=e.which;t!=l.SHIFT&amp;amp;&amp;amp;t!=l.CTRL&amp;amp;&amp;amp;t!=l.ALT&amp;amp;&amp;amp;t!=l.TAB&amp;amp;&amp;amp;r.handleSearch(e)}})},e.prototype._transferTabIndex=function(e){this.$search.attr(&amp;quot;tabindex&amp;quot;,this.$selection.attr(&amp;quot;tabindex&amp;quot;)),this.$selection.attr(&amp;quot;tabindex&amp;quot;,&amp;quot;-1&amp;quot;)},e.prototype.createPlaceholder=function(e,t){this.$search.attr(&amp;quot;placeholder&amp;quot;,t.text)},e.prototype.update=function(e,t){var n=this.$search[0]==document.activeElement;this.$search.attr(&amp;quot;placeholder&amp;quot;,&amp;quot;&amp;quot;),e.call(this,t),this.$selection.find(&amp;quot;.select2-selection__rendered&amp;quot;).append(this.$searchContainer),this.resizeSearch(),n&amp;amp;&amp;amp;this.$search.trigger(&amp;quot;focus&amp;quot;)},e.prototype.handleSearch=function(){if(this.resizeSearch(),!this._keyUpPrevented){var e=this.$search.val();this.trigger(&amp;quot;query&amp;quot;,{term:e})}this._keyUpPrevented=!1},e.prototype.searchRemoveChoice=function(e,t){this.trigger(&amp;quot;unselect&amp;quot;,{data:t}),this.$search.val(t.text),this.handleSearch()},e.prototype.resizeSearch=function(){this.$search.css(&amp;quot;width&amp;quot;,&amp;quot;25px&amp;quot;);var e=&amp;quot;&amp;quot;;&amp;quot;&amp;quot;!==this.$search.attr(&amp;quot;placeholder&amp;quot;)?e=this.$selection.find(&amp;quot;.select2-selection__rendered&amp;quot;).width():e=.75*(this.$search.val().length+1)+&amp;quot;em&amp;quot;;this.$search.css(&amp;quot;width&amp;quot;,e)},e}),e.define(&amp;quot;select2/selection/eventRelay&amp;quot;,[&amp;quot;jquery&amp;quot;],function(s){function e(){}return e.prototype.bind=function(e,t,n){var r=this,i=[&amp;quot;open&amp;quot;,&amp;quot;opening&amp;quot;,&amp;quot;close&amp;quot;,&amp;quot;closing&amp;quot;,&amp;quot;select&amp;quot;,&amp;quot;selecting&amp;quot;,&amp;quot;unselect&amp;quot;,&amp;quot;unselecting&amp;quot;,&amp;quot;clear&amp;quot;,&amp;quot;clearing&amp;quot;],o=[&amp;quot;opening&amp;quot;,&amp;quot;closing&amp;quot;,&amp;quot;selecting&amp;quot;,&amp;quot;unselecting&amp;quot;,&amp;quot;clearing&amp;quot;];e.call(this,t,n),t.on(&amp;quot;*&amp;quot;,function(e,t){if(-1!==s.inArray(e,i)){t=t||{};var n=s.Event(&amp;quot;select2:&amp;quot;+e,{params:t});r.$element.trigger(n),-1!==s.inArray(e,o)&amp;amp;&amp;amp;(t.prevented=n.isDefaultPrevented())}})},e}),e.define(&amp;quot;select2/translation&amp;quot;,[&amp;quot;jquery&amp;quot;,&amp;quot;require&amp;quot;],function(t,n){function r(e){this.dict=e||{}}return r.prototype.all=function(){return this.dict},r.prototype.get=function(e){return this.dict[e]},r.prototype.extend=function(e){this.dict=t.extend({},e.all(),this.dict)},r._cache={},r.loadPath=function(e){if(!(e in r._cache)){var t=n(e);r._cache[e]=t}return new r(r._cache[e])},r}),e.define(&amp;quot;select2/diacritics&amp;quot;,[],function(){return{&amp;quot;Ⓐ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ａ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;À&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Á&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Â&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ầ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ấ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ẫ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ẩ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ã&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ā&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ă&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ằ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ắ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ẵ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ẳ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ȧ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ǡ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ä&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ǟ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ả&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Å&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ǻ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ǎ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ȁ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ȃ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ạ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ậ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ặ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ḁ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ą&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ⱥ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ɐ&amp;quot;:&amp;quot;A&amp;quot;,&amp;quot;Ꜳ&amp;quot;:&amp;quot;AA&amp;quot;,&amp;quot;Æ&amp;quot;:&amp;quot;AE&amp;quot;,&amp;quot;Ǽ&amp;quot;:&amp;quot;AE&amp;quot;,&amp;quot;Ǣ&amp;quot;:&amp;quot;AE&amp;quot;,&amp;quot;Ꜵ&amp;quot;:&amp;quot;AO&amp;quot;,&amp;quot;Ꜷ&amp;quot;:&amp;quot;AU&amp;quot;,&amp;quot;Ꜹ&amp;quot;:&amp;quot;AV&amp;quot;,&amp;quot;Ꜻ&amp;quot;:&amp;quot;AV&amp;quot;,&amp;quot;Ꜽ&amp;quot;:&amp;quot;AY&amp;quot;,&amp;quot;Ⓑ&amp;quot;:&amp;quot;B&amp;quot;,&amp;quot;Ｂ&amp;quot;:&amp;quot;B&amp;quot;,&amp;quot;Ḃ&amp;quot;:&amp;quot;B&amp;quot;,&amp;quot;Ḅ&amp;quot;:&amp;quot;B&amp;quot;,&amp;quot;Ḇ&amp;quot;:&amp;quot;B&amp;quot;,&amp;quot;Ƀ&amp;quot;:&amp;quot;B&amp;quot;,&amp;quot;Ƃ&amp;quot;:&amp;quot;B&amp;quot;,&amp;quot;Ɓ&amp;quot;:&amp;quot;B&amp;quot;,&amp;quot;Ⓒ&amp;quot;:&amp;quot;C&amp;quot;,&amp;quot;Ｃ&amp;quot;:&amp;quot;C&amp;quot;,&amp;quot;Ć&amp;quot;:&amp;quot;C&amp;quot;,&amp;quot;Ĉ&amp;quot;:&amp;quot;C&amp;quot;,&amp;quot;Ċ&amp;quot;:&amp;quot;C&amp;quot;,&amp;quot;Č&amp;quot;:&amp;quot;C&amp;quot;,&amp;quot;Ç&amp;quot;:&amp;quot;C&amp;quot;,&amp;quot;Ḉ&amp;quot;:&amp;quot;C&amp;quot;,&amp;quot;Ƈ&amp;quot;:&amp;quot;C&amp;quot;,&amp;quot;Ȼ&amp;quot;:&amp;quot;C&amp;quot;,&amp;quot;Ꜿ&amp;quot;:&amp;quot;C&amp;quot;,&amp;quot;Ⓓ&amp;quot;:&amp;quot;D&amp;quot;,&amp;quot;Ｄ&amp;quot;:&amp;quot;D&amp;quot;,&amp;quot;Ḋ&amp;quot;:&amp;quot;D&amp;quot;,&amp;quot;Ď&amp;quot;:&amp;quot;D&amp;quot;,&amp;quot;Ḍ&amp;quot;:&amp;quot;D&amp;quot;,&amp;quot;Ḑ&amp;quot;:&amp;quot;D&amp;quot;,&amp;quot;Ḓ&amp;quot;:&amp;quot;D&amp;quot;,&amp;quot;Ḏ&amp;quot;:&amp;quot;D&amp;quot;,&amp;quot;Đ&amp;quot;:&amp;quot;D&amp;quot;,&amp;quot;Ƌ&amp;quot;:&amp;quot;D&amp;quot;,&amp;quot;Ɗ&amp;quot;:&amp;quot;D&amp;quot;,&amp;quot;Ɖ&amp;quot;:&amp;quot;D&amp;quot;,&amp;quot;Ꝺ&amp;quot;:&amp;quot;D&amp;quot;,&amp;quot;Ǳ&amp;quot;:&amp;quot;DZ&amp;quot;,&amp;quot;Ǆ&amp;quot;:&amp;quot;DZ&amp;quot;,&amp;quot;ǲ&amp;quot;:&amp;quot;Dz&amp;quot;,&amp;quot;ǅ&amp;quot;:&amp;quot;Dz&amp;quot;,&amp;quot;Ⓔ&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ｅ&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;È&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;É&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ê&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ề&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ế&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ễ&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ể&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ẽ&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ē&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ḕ&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ḗ&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ĕ&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ė&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ë&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ẻ&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ě&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ȅ&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ȇ&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ẹ&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ệ&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ȩ&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ḝ&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ę&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ḙ&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ḛ&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ɛ&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ǝ&amp;quot;:&amp;quot;E&amp;quot;,&amp;quot;Ⓕ&amp;quot;:&amp;quot;F&amp;quot;,&amp;quot;Ｆ&amp;quot;:&amp;quot;F&amp;quot;,&amp;quot;Ḟ&amp;quot;:&amp;quot;F&amp;quot;,&amp;quot;Ƒ&amp;quot;:&amp;quot;F&amp;quot;,&amp;quot;Ꝼ&amp;quot;:&amp;quot;F&amp;quot;,&amp;quot;Ⓖ&amp;quot;:&amp;quot;G&amp;quot;,&amp;quot;Ｇ&amp;quot;:&amp;quot;G&amp;quot;,&amp;quot;Ǵ&amp;quot;:&amp;quot;G&amp;quot;,&amp;quot;Ĝ&amp;quot;:&amp;quot;G&amp;quot;,&amp;quot;Ḡ&amp;quot;:&amp;quot;G&amp;quot;,&amp;quot;Ğ&amp;quot;:&amp;quot;G&amp;quot;,&amp;quot;Ġ&amp;quot;:&amp;quot;G&amp;quot;,&amp;quot;Ǧ&amp;quot;:&amp;quot;G&amp;quot;,&amp;quot;Ģ&amp;quot;:&amp;quot;G&amp;quot;,&amp;quot;Ǥ&amp;quot;:&amp;quot;G&amp;quot;,&amp;quot;Ɠ&amp;quot;:&amp;quot;G&amp;quot;,&amp;quot;Ꞡ&amp;quot;:&amp;quot;G&amp;quot;,&amp;quot;Ᵹ&amp;quot;:&amp;quot;G&amp;quot;,&amp;quot;Ꝿ&amp;quot;:&amp;quot;G&amp;quot;,&amp;quot;Ⓗ&amp;quot;:&amp;quot;H&amp;quot;,&amp;quot;Ｈ&amp;quot;:&amp;quot;H&amp;quot;,&amp;quot;Ĥ&amp;quot;:&amp;quot;H&amp;quot;,&amp;quot;Ḣ&amp;quot;:&amp;quot;H&amp;quot;,&amp;quot;Ḧ&amp;quot;:&amp;quot;H&amp;quot;,&amp;quot;Ȟ&amp;quot;:&amp;quot;H&amp;quot;,&amp;quot;Ḥ&amp;quot;:&amp;quot;H&amp;quot;,&amp;quot;Ḩ&amp;quot;:&amp;quot;H&amp;quot;,&amp;quot;Ḫ&amp;quot;:&amp;quot;H&amp;quot;,&amp;quot;Ħ&amp;quot;:&amp;quot;H&amp;quot;,&amp;quot;Ⱨ&amp;quot;:&amp;quot;H&amp;quot;,&amp;quot;Ⱶ&amp;quot;:&amp;quot;H&amp;quot;,&amp;quot;Ɥ&amp;quot;:&amp;quot;H&amp;quot;,&amp;quot;Ⓘ&amp;quot;:&amp;quot;I&amp;quot;,&amp;quot;Ｉ&amp;quot;:&amp;quot;I&amp;quot;,&amp;quot;Ì&amp;quot;:&amp;quot;I&amp;quot;,&amp;quot;Í&amp;quot;:&amp;quot;I&amp;quot;,&amp;quot;Î&amp;quot;:&amp;quot;I&amp;quot;,&amp;quot;Ĩ&amp;quot;:&amp;quot;I&amp;quot;,&amp;quot;Ī&amp;quot;:&amp;quot;I&amp;quot;,&amp;quot;Ĭ&amp;quot;:&amp;quot;I&amp;quot;,&amp;quot;İ&amp;quot;:&amp;quot;I&amp;quot;,&amp;quot;Ï&amp;quot;:&amp;quot;I&amp;quot;,&amp;quot;Ḯ&amp;quot;:&amp;quot;I&amp;quot;,&amp;quot;Ỉ&amp;quot;:&amp;quot;I&amp;quot;,&amp;quot;Ǐ&amp;quot;:&amp;quot;I&amp;quot;,&amp;quot;Ȉ&amp;quot;:&amp;quot;I&amp;quot;,&amp;quot;Ȋ&amp;quot;:&amp;quot;I&amp;quot;,&amp;quot;Ị&amp;quot;:&amp;quot;I&amp;quot;,&amp;quot;Į&amp;quot;:&amp;quot;I&amp;quot;,&amp;quot;Ḭ&amp;quot;:&amp;quot;I&amp;quot;,&amp;quot;Ɨ&amp;quot;:&amp;quot;I&amp;quot;,&amp;quot;Ⓙ&amp;quot;:&amp;quot;J&amp;quot;,&amp;quot;Ｊ&amp;quot;:&amp;quot;J&amp;quot;,&amp;quot;Ĵ&amp;quot;:&amp;quot;J&amp;quot;,&amp;quot;Ɉ&amp;quot;:&amp;quot;J&amp;quot;,&amp;quot;Ⓚ&amp;quot;:&amp;quot;K&amp;quot;,&amp;quot;Ｋ&amp;quot;:&amp;quot;K&amp;quot;,&amp;quot;Ḱ&amp;quot;:&amp;quot;K&amp;quot;,&amp;quot;Ǩ&amp;quot;:&amp;quot;K&amp;quot;,&amp;quot;Ḳ&amp;quot;:&amp;quot;K&amp;quot;,&amp;quot;Ķ&amp;quot;:&amp;quot;K&amp;quot;,&amp;quot;Ḵ&amp;quot;:&amp;quot;K&amp;quot;,&amp;quot;Ƙ&amp;quot;:&amp;quot;K&amp;quot;,&amp;quot;Ⱪ&amp;quot;:&amp;quot;K&amp;quot;,&amp;quot;Ꝁ&amp;quot;:&amp;quot;K&amp;quot;,&amp;quot;Ꝃ&amp;quot;:&amp;quot;K&amp;quot;,&amp;quot;Ꝅ&amp;quot;:&amp;quot;K&amp;quot;,&amp;quot;Ꞣ&amp;quot;:&amp;quot;K&amp;quot;,&amp;quot;Ⓛ&amp;quot;:&amp;quot;L&amp;quot;,&amp;quot;Ｌ&amp;quot;:&amp;quot;L&amp;quot;,&amp;quot;Ŀ&amp;quot;:&amp;quot;L&amp;quot;,&amp;quot;Ĺ&amp;quot;:&amp;quot;L&amp;quot;,&amp;quot;Ľ&amp;quot;:&amp;quot;L&amp;quot;,&amp;quot;Ḷ&amp;quot;:&amp;quot;L&amp;quot;,&amp;quot;Ḹ&amp;quot;:&amp;quot;L&amp;quot;,&amp;quot;Ļ&amp;quot;:&amp;quot;L&amp;quot;,&amp;quot;Ḽ&amp;quot;:&amp;quot;L&amp;quot;,&amp;quot;Ḻ&amp;quot;:&amp;quot;L&amp;quot;,&amp;quot;Ł&amp;quot;:&amp;quot;L&amp;quot;,&amp;quot;Ƚ&amp;quot;:&amp;quot;L&amp;quot;,&amp;quot;Ɫ&amp;quot;:&amp;quot;L&amp;quot;,&amp;quot;Ⱡ&amp;quot;:&amp;quot;L&amp;quot;,&amp;quot;Ꝉ&amp;quot;:&amp;quot;L&amp;quot;,&amp;quot;Ꝇ&amp;quot;:&amp;quot;L&amp;quot;,&amp;quot;Ꞁ&amp;quot;:&amp;quot;L&amp;quot;,&amp;quot;Ǉ&amp;quot;:&amp;quot;LJ&amp;quot;,&amp;quot;ǈ&amp;quot;:&amp;quot;Lj&amp;quot;,&amp;quot;Ⓜ&amp;quot;:&amp;quot;M&amp;quot;,&amp;quot;Ｍ&amp;quot;:&amp;quot;M&amp;quot;,&amp;quot;Ḿ&amp;quot;:&amp;quot;M&amp;quot;,&amp;quot;Ṁ&amp;quot;:&amp;quot;M&amp;quot;,&amp;quot;Ṃ&amp;quot;:&amp;quot;M&amp;quot;,&amp;quot;Ɱ&amp;quot;:&amp;quot;M&amp;quot;,&amp;quot;Ɯ&amp;quot;:&amp;quot;M&amp;quot;,&amp;quot;Ⓝ&amp;quot;:&amp;quot;N&amp;quot;,&amp;quot;Ｎ&amp;quot;:&amp;quot;N&amp;quot;,&amp;quot;Ǹ&amp;quot;:&amp;quot;N&amp;quot;,&amp;quot;Ń&amp;quot;:&amp;quot;N&amp;quot;,&amp;quot;Ñ&amp;quot;:&amp;quot;N&amp;quot;,&amp;quot;Ṅ&amp;quot;:&amp;quot;N&amp;quot;,&amp;quot;Ň&amp;quot;:&amp;quot;N&amp;quot;,&amp;quot;Ṇ&amp;quot;:&amp;quot;N&amp;quot;,&amp;quot;Ņ&amp;quot;:&amp;quot;N&amp;quot;,&amp;quot;Ṋ&amp;quot;:&amp;quot;N&amp;quot;,&amp;quot;Ṉ&amp;quot;:&amp;quot;N&amp;quot;,&amp;quot;Ƞ&amp;quot;:&amp;quot;N&amp;quot;,&amp;quot;Ɲ&amp;quot;:&amp;quot;N&amp;quot;,&amp;quot;Ꞑ&amp;quot;:&amp;quot;N&amp;quot;,&amp;quot;Ꞥ&amp;quot;:&amp;quot;N&amp;quot;,&amp;quot;Ǌ&amp;quot;:&amp;quot;NJ&amp;quot;,&amp;quot;ǋ&amp;quot;:&amp;quot;Nj&amp;quot;,&amp;quot;Ⓞ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ｏ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ò&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ó&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ô&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ồ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ố&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ỗ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ổ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Õ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ṍ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ȭ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ṏ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ō&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ṑ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ṓ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ŏ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ȯ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ȱ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ö&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ȫ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ỏ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ő&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ǒ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ȍ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ȏ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ơ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ờ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ớ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ỡ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ở&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ợ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ọ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ộ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ǫ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ǭ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ø&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ǿ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ɔ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ɵ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ꝋ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Ꝍ&amp;quot;:&amp;quot;O&amp;quot;,&amp;quot;Œ&amp;quot;:&amp;quot;OE&amp;quot;,&amp;quot;Ƣ&amp;quot;:&amp;quot;OI&amp;quot;,&amp;quot;Ꝏ&amp;quot;:&amp;quot;OO&amp;quot;,&amp;quot;Ȣ&amp;quot;:&amp;quot;OU&amp;quot;,&amp;quot;Ⓟ&amp;quot;:&amp;quot;P&amp;quot;,&amp;quot;Ｐ&amp;quot;:&amp;quot;P&amp;quot;,&amp;quot;Ṕ&amp;quot;:&amp;quot;P&amp;quot;,&amp;quot;Ṗ&amp;quot;:&amp;quot;P&amp;quot;,&amp;quot;Ƥ&amp;quot;:&amp;quot;P&amp;quot;,&amp;quot;Ᵽ&amp;quot;:&amp;quot;P&amp;quot;,&amp;quot;Ꝑ&amp;quot;:&amp;quot;P&amp;quot;,&amp;quot;Ꝓ&amp;quot;:&amp;quot;P&amp;quot;,&amp;quot;Ꝕ&amp;quot;:&amp;quot;P&amp;quot;,&amp;quot;Ⓠ&amp;quot;:&amp;quot;Q&amp;quot;,&amp;quot;Ｑ&amp;quot;:&amp;quot;Q&amp;quot;,&amp;quot;Ꝗ&amp;quot;:&amp;quot;Q&amp;quot;,&amp;quot;Ꝙ&amp;quot;:&amp;quot;Q&amp;quot;,&amp;quot;Ɋ&amp;quot;:&amp;quot;Q&amp;quot;,&amp;quot;Ⓡ&amp;quot;:&amp;quot;R&amp;quot;,&amp;quot;Ｒ&amp;quot;:&amp;quot;R&amp;quot;,&amp;quot;Ŕ&amp;quot;:&amp;quot;R&amp;quot;,&amp;quot;Ṙ&amp;quot;:&amp;quot;R&amp;quot;,&amp;quot;Ř&amp;quot;:&amp;quot;R&amp;quot;,&amp;quot;Ȑ&amp;quot;:&amp;quot;R&amp;quot;,&amp;quot;Ȓ&amp;quot;:&amp;quot;R&amp;quot;,&amp;quot;Ṛ&amp;quot;:&amp;quot;R&amp;quot;,&amp;quot;Ṝ&amp;quot;:&amp;quot;R&amp;quot;,&amp;quot;Ŗ&amp;quot;:&amp;quot;R&amp;quot;,&amp;quot;Ṟ&amp;quot;:&amp;quot;R&amp;quot;,&amp;quot;Ɍ&amp;quot;:&amp;quot;R&amp;quot;,&amp;quot;Ɽ&amp;quot;:&amp;quot;R&amp;quot;,&amp;quot;Ꝛ&amp;quot;:&amp;quot;R&amp;quot;,&amp;quot;Ꞧ&amp;quot;:&amp;quot;R&amp;quot;,&amp;quot;Ꞃ&amp;quot;:&amp;quot;R&amp;quot;,&amp;quot;Ⓢ&amp;quot;:&amp;quot;S&amp;quot;,&amp;quot;Ｓ&amp;quot;:&amp;quot;S&amp;quot;,&amp;quot;ẞ&amp;quot;:&amp;quot;S&amp;quot;,&amp;quot;Ś&amp;quot;:&amp;quot;S&amp;quot;,&amp;quot;Ṥ&amp;quot;:&amp;quot;S&amp;quot;,&amp;quot;Ŝ&amp;quot;:&amp;quot;S&amp;quot;,&amp;quot;Ṡ&amp;quot;:&amp;quot;S&amp;quot;,&amp;quot;Š&amp;quot;:&amp;quot;S&amp;quot;,&amp;quot;Ṧ&amp;quot;:&amp;quot;S&amp;quot;,&amp;quot;Ṣ&amp;quot;:&amp;quot;S&amp;quot;,&amp;quot;Ṩ&amp;quot;:&amp;quot;S&amp;quot;,&amp;quot;Ș&amp;quot;:&amp;quot;S&amp;quot;,&amp;quot;Ş&amp;quot;:&amp;quot;S&amp;quot;,&amp;quot;Ȿ&amp;quot;:&amp;quot;S&amp;quot;,&amp;quot;Ꞩ&amp;quot;:&amp;quot;S&amp;quot;,&amp;quot;Ꞅ&amp;quot;:&amp;quot;S&amp;quot;,&amp;quot;Ⓣ&amp;quot;:&amp;quot;T&amp;quot;,&amp;quot;Ｔ&amp;quot;:&amp;quot;T&amp;quot;,&amp;quot;Ṫ&amp;quot;:&amp;quot;T&amp;quot;,&amp;quot;Ť&amp;quot;:&amp;quot;T&amp;quot;,&amp;quot;Ṭ&amp;quot;:&amp;quot;T&amp;quot;,&amp;quot;Ț&amp;quot;:&amp;quot;T&amp;quot;,&amp;quot;Ţ&amp;quot;:&amp;quot;T&amp;quot;,&amp;quot;Ṱ&amp;quot;:&amp;quot;T&amp;quot;,&amp;quot;Ṯ&amp;quot;:&amp;quot;T&amp;quot;,&amp;quot;Ŧ&amp;quot;:&amp;quot;T&amp;quot;,&amp;quot;Ƭ&amp;quot;:&amp;quot;T&amp;quot;,&amp;quot;Ʈ&amp;quot;:&amp;quot;T&amp;quot;,&amp;quot;Ⱦ&amp;quot;:&amp;quot;T&amp;quot;,&amp;quot;Ꞇ&amp;quot;:&amp;quot;T&amp;quot;,&amp;quot;Ꜩ&amp;quot;:&amp;quot;TZ&amp;quot;,&amp;quot;Ⓤ&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ｕ&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ù&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ú&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Û&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ũ&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ṹ&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ū&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ṻ&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ŭ&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ü&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ǜ&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ǘ&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ǖ&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ǚ&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ủ&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ů&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ű&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ǔ&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ȕ&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ȗ&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ư&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ừ&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ứ&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ữ&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ử&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ự&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ụ&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ṳ&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ų&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ṷ&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ṵ&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ʉ&amp;quot;:&amp;quot;U&amp;quot;,&amp;quot;Ⓥ&amp;quot;:&amp;quot;V&amp;quot;,&amp;quot;Ｖ&amp;quot;:&amp;quot;V&amp;quot;,&amp;quot;Ṽ&amp;quot;:&amp;quot;V&amp;quot;,&amp;quot;Ṿ&amp;quot;:&amp;quot;V&amp;quot;,&amp;quot;Ʋ&amp;quot;:&amp;quot;V&amp;quot;,&amp;quot;Ꝟ&amp;quot;:&amp;quot;V&amp;quot;,&amp;quot;Ʌ&amp;quot;:&amp;quot;V&amp;quot;,&amp;quot;Ꝡ&amp;quot;:&amp;quot;VY&amp;quot;,&amp;quot;Ⓦ&amp;quot;:&amp;quot;W&amp;quot;,&amp;quot;Ｗ&amp;quot;:&amp;quot;W&amp;quot;,&amp;quot;Ẁ&amp;quot;:&amp;quot;W&amp;quot;,&amp;quot;Ẃ&amp;quot;:&amp;quot;W&amp;quot;,&amp;quot;Ŵ&amp;quot;:&amp;quot;W&amp;quot;,&amp;quot;Ẇ&amp;quot;:&amp;quot;W&amp;quot;,&amp;quot;Ẅ&amp;quot;:&amp;quot;W&amp;quot;,&amp;quot;Ẉ&amp;quot;:&amp;quot;W&amp;quot;,&amp;quot;Ⱳ&amp;quot;:&amp;quot;W&amp;quot;,&amp;quot;Ⓧ&amp;quot;:&amp;quot;X&amp;quot;,&amp;quot;Ｘ&amp;quot;:&amp;quot;X&amp;quot;,&amp;quot;Ẋ&amp;quot;:&amp;quot;X&amp;quot;,&amp;quot;Ẍ&amp;quot;:&amp;quot;X&amp;quot;,&amp;quot;Ⓨ&amp;quot;:&amp;quot;Y&amp;quot;,&amp;quot;Ｙ&amp;quot;:&amp;quot;Y&amp;quot;,&amp;quot;Ỳ&amp;quot;:&amp;quot;Y&amp;quot;,&amp;quot;Ý&amp;quot;:&amp;quot;Y&amp;quot;,&amp;quot;Ŷ&amp;quot;:&amp;quot;Y&amp;quot;,&amp;quot;Ỹ&amp;quot;:&amp;quot;Y&amp;quot;,&amp;quot;Ȳ&amp;quot;:&amp;quot;Y&amp;quot;,&amp;quot;Ẏ&amp;quot;:&amp;quot;Y&amp;quot;,&amp;quot;Ÿ&amp;quot;:&amp;quot;Y&amp;quot;,&amp;quot;Ỷ&amp;quot;:&amp;quot;Y&amp;quot;,&amp;quot;Ỵ&amp;quot;:&amp;quot;Y&amp;quot;,&amp;quot;Ƴ&amp;quot;:&amp;quot;Y&amp;quot;,&amp;quot;Ɏ&amp;quot;:&amp;quot;Y&amp;quot;,&amp;quot;Ỿ&amp;quot;:&amp;quot;Y&amp;quot;,&amp;quot;Ⓩ&amp;quot;:&amp;quot;Z&amp;quot;,&amp;quot;Ｚ&amp;quot;:&amp;quot;Z&amp;quot;,&amp;quot;Ź&amp;quot;:&amp;quot;Z&amp;quot;,&amp;quot;Ẑ&amp;quot;:&amp;quot;Z&amp;quot;,&amp;quot;Ż&amp;quot;:&amp;quot;Z&amp;quot;,&amp;quot;Ž&amp;quot;:&amp;quot;Z&amp;quot;,&amp;quot;Ẓ&amp;quot;:&amp;quot;Z&amp;quot;,&amp;quot;Ẕ&amp;quot;:&amp;quot;Z&amp;quot;,&amp;quot;Ƶ&amp;quot;:&amp;quot;Z&amp;quot;,&amp;quot;Ȥ&amp;quot;:&amp;quot;Z&amp;quot;,&amp;quot;Ɀ&amp;quot;:&amp;quot;Z&amp;quot;,&amp;quot;Ⱬ&amp;quot;:&amp;quot;Z&amp;quot;,&amp;quot;Ꝣ&amp;quot;:&amp;quot;Z&amp;quot;,&amp;quot;ⓐ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ａ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ẚ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;à&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;á&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;â&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ầ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ấ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ẫ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ẩ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ã&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ā&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ă&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ằ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ắ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ẵ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ẳ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ȧ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ǡ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ä&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ǟ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ả&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;å&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ǻ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ǎ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ȁ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ȃ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ạ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ậ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ặ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ḁ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ą&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ⱥ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ɐ&amp;quot;:&amp;quot;a&amp;quot;,&amp;quot;ꜳ&amp;quot;:&amp;quot;aa&amp;quot;,&amp;quot;æ&amp;quot;:&amp;quot;ae&amp;quot;,&amp;quot;ǽ&amp;quot;:&amp;quot;ae&amp;quot;,&amp;quot;ǣ&amp;quot;:&amp;quot;ae&amp;quot;,&amp;quot;ꜵ&amp;quot;:&amp;quot;ao&amp;quot;,&amp;quot;ꜷ&amp;quot;:&amp;quot;au&amp;quot;,&amp;quot;ꜹ&amp;quot;:&amp;quot;av&amp;quot;,&amp;quot;ꜻ&amp;quot;:&amp;quot;av&amp;quot;,&amp;quot;ꜽ&amp;quot;:&amp;quot;ay&amp;quot;,&amp;quot;ⓑ&amp;quot;:&amp;quot;b&amp;quot;,&amp;quot;ｂ&amp;quot;:&amp;quot;b&amp;quot;,&amp;quot;ḃ&amp;quot;:&amp;quot;b&amp;quot;,&amp;quot;ḅ&amp;quot;:&amp;quot;b&amp;quot;,&amp;quot;ḇ&amp;quot;:&amp;quot;b&amp;quot;,&amp;quot;ƀ&amp;quot;:&amp;quot;b&amp;quot;,&amp;quot;ƃ&amp;quot;:&amp;quot;b&amp;quot;,&amp;quot;ɓ&amp;quot;:&amp;quot;b&amp;quot;,&amp;quot;ⓒ&amp;quot;:&amp;quot;c&amp;quot;,&amp;quot;ｃ&amp;quot;:&amp;quot;c&amp;quot;,&amp;quot;ć&amp;quot;:&amp;quot;c&amp;quot;,&amp;quot;ĉ&amp;quot;:&amp;quot;c&amp;quot;,&amp;quot;ċ&amp;quot;:&amp;quot;c&amp;quot;,&amp;quot;č&amp;quot;:&amp;quot;c&amp;quot;,&amp;quot;ç&amp;quot;:&amp;quot;c&amp;quot;,&amp;quot;ḉ&amp;quot;:&amp;quot;c&amp;quot;,&amp;quot;ƈ&amp;quot;:&amp;quot;c&amp;quot;,&amp;quot;ȼ&amp;quot;:&amp;quot;c&amp;quot;,&amp;quot;ꜿ&amp;quot;:&amp;quot;c&amp;quot;,&amp;quot;ↄ&amp;quot;:&amp;quot;c&amp;quot;,&amp;quot;ⓓ&amp;quot;:&amp;quot;d&amp;quot;,&amp;quot;ｄ&amp;quot;:&amp;quot;d&amp;quot;,&amp;quot;ḋ&amp;quot;:&amp;quot;d&amp;quot;,&amp;quot;ď&amp;quot;:&amp;quot;d&amp;quot;,&amp;quot;ḍ&amp;quot;:&amp;quot;d&amp;quot;,&amp;quot;ḑ&amp;quot;:&amp;quot;d&amp;quot;,&amp;quot;ḓ&amp;quot;:&amp;quot;d&amp;quot;,&amp;quot;ḏ&amp;quot;:&amp;quot;d&amp;quot;,&amp;quot;đ&amp;quot;:&amp;quot;d&amp;quot;,&amp;quot;ƌ&amp;quot;:&amp;quot;d&amp;quot;,&amp;quot;ɖ&amp;quot;:&amp;quot;d&amp;quot;,&amp;quot;ɗ&amp;quot;:&amp;quot;d&amp;quot;,&amp;quot;ꝺ&amp;quot;:&amp;quot;d&amp;quot;,&amp;quot;ǳ&amp;quot;:&amp;quot;dz&amp;quot;,&amp;quot;ǆ&amp;quot;:&amp;quot;dz&amp;quot;,&amp;quot;ⓔ&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ｅ&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;è&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;é&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ê&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ề&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ế&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ễ&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ể&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ẽ&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ē&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ḕ&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ḗ&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ĕ&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ė&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ë&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ẻ&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ě&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ȅ&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ȇ&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ẹ&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ệ&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ȩ&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ḝ&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ę&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ḙ&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ḛ&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ɇ&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ɛ&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ǝ&amp;quot;:&amp;quot;e&amp;quot;,&amp;quot;ⓕ&amp;quot;:&amp;quot;f&amp;quot;,&amp;quot;ｆ&amp;quot;:&amp;quot;f&amp;quot;,&amp;quot;ḟ&amp;quot;:&amp;quot;f&amp;quot;,&amp;quot;ƒ&amp;quot;:&amp;quot;f&amp;quot;,&amp;quot;ꝼ&amp;quot;:&amp;quot;f&amp;quot;,&amp;quot;ⓖ&amp;quot;:&amp;quot;g&amp;quot;,&amp;quot;ｇ&amp;quot;:&amp;quot;g&amp;quot;,&amp;quot;ǵ&amp;quot;:&amp;quot;g&amp;quot;,&amp;quot;ĝ&amp;quot;:&amp;quot;g&amp;quot;,&amp;quot;ḡ&amp;quot;:&amp;quot;g&amp;quot;,&amp;quot;ğ&amp;quot;:&amp;quot;g&amp;quot;,&amp;quot;ġ&amp;quot;:&amp;quot;g&amp;quot;,&amp;quot;ǧ&amp;quot;:&amp;quot;g&amp;quot;,&amp;quot;ģ&amp;quot;:&amp;quot;g&amp;quot;,&amp;quot;ǥ&amp;quot;:&amp;quot;g&amp;quot;,&amp;quot;ɠ&amp;quot;:&amp;quot;g&amp;quot;,&amp;quot;ꞡ&amp;quot;:&amp;quot;g&amp;quot;,&amp;quot;ᵹ&amp;quot;:&amp;quot;g&amp;quot;,&amp;quot;ꝿ&amp;quot;:&amp;quot;g&amp;quot;,&amp;quot;ⓗ&amp;quot;:&amp;quot;h&amp;quot;,&amp;quot;ｈ&amp;quot;:&amp;quot;h&amp;quot;,&amp;quot;ĥ&amp;quot;:&amp;quot;h&amp;quot;,&amp;quot;ḣ&amp;quot;:&amp;quot;h&amp;quot;,&amp;quot;ḧ&amp;quot;:&amp;quot;h&amp;quot;,&amp;quot;ȟ&amp;quot;:&amp;quot;h&amp;quot;,&amp;quot;ḥ&amp;quot;:&amp;quot;h&amp;quot;,&amp;quot;ḩ&amp;quot;:&amp;quot;h&amp;quot;,&amp;quot;ḫ&amp;quot;:&amp;quot;h&amp;quot;,&amp;quot;ẖ&amp;quot;:&amp;quot;h&amp;quot;,&amp;quot;ħ&amp;quot;:&amp;quot;h&amp;quot;,&amp;quot;ⱨ&amp;quot;:&amp;quot;h&amp;quot;,&amp;quot;ⱶ&amp;quot;:&amp;quot;h&amp;quot;,&amp;quot;ɥ&amp;quot;:&amp;quot;h&amp;quot;,&amp;quot;ƕ&amp;quot;:&amp;quot;hv&amp;quot;,&amp;quot;ⓘ&amp;quot;:&amp;quot;i&amp;quot;,&amp;quot;ｉ&amp;quot;:&amp;quot;i&amp;quot;,&amp;quot;ì&amp;quot;:&amp;quot;i&amp;quot;,&amp;quot;í&amp;quot;:&amp;quot;i&amp;quot;,&amp;quot;î&amp;quot;:&amp;quot;i&amp;quot;,&amp;quot;ĩ&amp;quot;:&amp;quot;i&amp;quot;,&amp;quot;ī&amp;quot;:&amp;quot;i&amp;quot;,&amp;quot;ĭ&amp;quot;:&amp;quot;i&amp;quot;,&amp;quot;ï&amp;quot;:&amp;quot;i&amp;quot;,&amp;quot;ḯ&amp;quot;:&amp;quot;i&amp;quot;,&amp;quot;ỉ&amp;quot;:&amp;quot;i&amp;quot;,&amp;quot;ǐ&amp;quot;:&amp;quot;i&amp;quot;,&amp;quot;ȉ&amp;quot;:&amp;quot;i&amp;quot;,&amp;quot;ȋ&amp;quot;:&amp;quot;i&amp;quot;,&amp;quot;ị&amp;quot;:&amp;quot;i&amp;quot;,&amp;quot;į&amp;quot;:&amp;quot;i&amp;quot;,&amp;quot;ḭ&amp;quot;:&amp;quot;i&amp;quot;,&amp;quot;ɨ&amp;quot;:&amp;quot;i&amp;quot;,&amp;quot;ı&amp;quot;:&amp;quot;i&amp;quot;,&amp;quot;ⓙ&amp;quot;:&amp;quot;j&amp;quot;,&amp;quot;ｊ&amp;quot;:&amp;quot;j&amp;quot;,&amp;quot;ĵ&amp;quot;:&amp;quot;j&amp;quot;,&amp;quot;ǰ&amp;quot;:&amp;quot;j&amp;quot;,&amp;quot;ɉ&amp;quot;:&amp;quot;j&amp;quot;,&amp;quot;ⓚ&amp;quot;:&amp;quot;k&amp;quot;,&amp;quot;ｋ&amp;quot;:&amp;quot;k&amp;quot;,&amp;quot;ḱ&amp;quot;:&amp;quot;k&amp;quot;,&amp;quot;ǩ&amp;quot;:&amp;quot;k&amp;quot;,&amp;quot;ḳ&amp;quot;:&amp;quot;k&amp;quot;,&amp;quot;ķ&amp;quot;:&amp;quot;k&amp;quot;,&amp;quot;ḵ&amp;quot;:&amp;quot;k&amp;quot;,&amp;quot;ƙ&amp;quot;:&amp;quot;k&amp;quot;,&amp;quot;ⱪ&amp;quot;:&amp;quot;k&amp;quot;,&amp;quot;ꝁ&amp;quot;:&amp;quot;k&amp;quot;,&amp;quot;ꝃ&amp;quot;:&amp;quot;k&amp;quot;,&amp;quot;ꝅ&amp;quot;:&amp;quot;k&amp;quot;,&amp;quot;ꞣ&amp;quot;:&amp;quot;k&amp;quot;,&amp;quot;ⓛ&amp;quot;:&amp;quot;l&amp;quot;,&amp;quot;ｌ&amp;quot;:&amp;quot;l&amp;quot;,&amp;quot;ŀ&amp;quot;:&amp;quot;l&amp;quot;,&amp;quot;ĺ&amp;quot;:&amp;quot;l&amp;quot;,&amp;quot;ľ&amp;quot;:&amp;quot;l&amp;quot;,&amp;quot;ḷ&amp;quot;:&amp;quot;l&amp;quot;,&amp;quot;ḹ&amp;quot;:&amp;quot;l&amp;quot;,&amp;quot;ļ&amp;quot;:&amp;quot;l&amp;quot;,&amp;quot;ḽ&amp;quot;:&amp;quot;l&amp;quot;,&amp;quot;ḻ&amp;quot;:&amp;quot;l&amp;quot;,&amp;quot;ſ&amp;quot;:&amp;quot;l&amp;quot;,&amp;quot;ł&amp;quot;:&amp;quot;l&amp;quot;,&amp;quot;ƚ&amp;quot;:&amp;quot;l&amp;quot;,&amp;quot;ɫ&amp;quot;:&amp;quot;l&amp;quot;,&amp;quot;ⱡ&amp;quot;:&amp;quot;l&amp;quot;,&amp;quot;ꝉ&amp;quot;:&amp;quot;l&amp;quot;,&amp;quot;ꞁ&amp;quot;:&amp;quot;l&amp;quot;,&amp;quot;ꝇ&amp;quot;:&amp;quot;l&amp;quot;,&amp;quot;ǉ&amp;quot;:&amp;quot;lj&amp;quot;,&amp;quot;ⓜ&amp;quot;:&amp;quot;m&amp;quot;,&amp;quot;ｍ&amp;quot;:&amp;quot;m&amp;quot;,&amp;quot;ḿ&amp;quot;:&amp;quot;m&amp;quot;,&amp;quot;ṁ&amp;quot;:&amp;quot;m&amp;quot;,&amp;quot;ṃ&amp;quot;:&amp;quot;m&amp;quot;,&amp;quot;ɱ&amp;quot;:&amp;quot;m&amp;quot;,&amp;quot;ɯ&amp;quot;:&amp;quot;m&amp;quot;,&amp;quot;ⓝ&amp;quot;:&amp;quot;n&amp;quot;,&amp;quot;ｎ&amp;quot;:&amp;quot;n&amp;quot;,&amp;quot;ǹ&amp;quot;:&amp;quot;n&amp;quot;,&amp;quot;ń&amp;quot;:&amp;quot;n&amp;quot;,&amp;quot;ñ&amp;quot;:&amp;quot;n&amp;quot;,&amp;quot;ṅ&amp;quot;:&amp;quot;n&amp;quot;,&amp;quot;ň&amp;quot;:&amp;quot;n&amp;quot;,&amp;quot;ṇ&amp;quot;:&amp;quot;n&amp;quot;,&amp;quot;ņ&amp;quot;:&amp;quot;n&amp;quot;,&amp;quot;ṋ&amp;quot;:&amp;quot;n&amp;quot;,&amp;quot;ṉ&amp;quot;:&amp;quot;n&amp;quot;,&amp;quot;ƞ&amp;quot;:&amp;quot;n&amp;quot;,&amp;quot;ɲ&amp;quot;:&amp;quot;n&amp;quot;,&amp;quot;ŉ&amp;quot;:&amp;quot;n&amp;quot;,&amp;quot;ꞑ&amp;quot;:&amp;quot;n&amp;quot;,&amp;quot;ꞥ&amp;quot;:&amp;quot;n&amp;quot;,&amp;quot;ǌ&amp;quot;:&amp;quot;nj&amp;quot;,&amp;quot;ⓞ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ｏ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ò&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ó&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ô&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ồ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ố&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ỗ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ổ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;õ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ṍ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ȭ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ṏ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ō&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ṑ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ṓ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ŏ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ȯ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ȱ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ö&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ȫ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ỏ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ő&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ǒ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ȍ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ȏ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ơ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ờ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ớ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ỡ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ở&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ợ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ọ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ộ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ǫ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ǭ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ø&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ǿ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ɔ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ꝋ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ꝍ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;ɵ&amp;quot;:&amp;quot;o&amp;quot;,&amp;quot;œ&amp;quot;:&amp;quot;oe&amp;quot;,&amp;quot;ƣ&amp;quot;:&amp;quot;oi&amp;quot;,&amp;quot;ȣ&amp;quot;:&amp;quot;ou&amp;quot;,&amp;quot;ꝏ&amp;quot;:&amp;quot;oo&amp;quot;,&amp;quot;ⓟ&amp;quot;:&amp;quot;p&amp;quot;,&amp;quot;ｐ&amp;quot;:&amp;quot;p&amp;quot;,&amp;quot;ṕ&amp;quot;:&amp;quot;p&amp;quot;,&amp;quot;ṗ&amp;quot;:&amp;quot;p&amp;quot;,&amp;quot;ƥ&amp;quot;:&amp;quot;p&amp;quot;,&amp;quot;ᵽ&amp;quot;:&amp;quot;p&amp;quot;,&amp;quot;ꝑ&amp;quot;:&amp;quot;p&amp;quot;,&amp;quot;ꝓ&amp;quot;:&amp;quot;p&amp;quot;,&amp;quot;ꝕ&amp;quot;:&amp;quot;p&amp;quot;,&amp;quot;ⓠ&amp;quot;:&amp;quot;q&amp;quot;,&amp;quot;ｑ&amp;quot;:&amp;quot;q&amp;quot;,&amp;quot;ɋ&amp;quot;:&amp;quot;q&amp;quot;,&amp;quot;ꝗ&amp;quot;:&amp;quot;q&amp;quot;,&amp;quot;ꝙ&amp;quot;:&amp;quot;q&amp;quot;,&amp;quot;ⓡ&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;ｒ&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;ŕ&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;ṙ&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;ř&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;ȑ&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;ȓ&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;ṛ&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;ṝ&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;ŗ&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;ṟ&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;ɍ&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;ɽ&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;ꝛ&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;ꞧ&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;ꞃ&amp;quot;:&amp;quot;r&amp;quot;,&amp;quot;ⓢ&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;ｓ&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;ß&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;ś&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;ṥ&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;ŝ&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;ṡ&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;š&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;ṧ&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;ṣ&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;ṩ&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;ș&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;ş&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;ȿ&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;ꞩ&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;ꞅ&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;ẛ&amp;quot;:&amp;quot;s&amp;quot;,&amp;quot;ⓣ&amp;quot;:&amp;quot;t&amp;quot;,&amp;quot;ｔ&amp;quot;:&amp;quot;t&amp;quot;,&amp;quot;ṫ&amp;quot;:&amp;quot;t&amp;quot;,&amp;quot;ẗ&amp;quot;:&amp;quot;t&amp;quot;,&amp;quot;ť&amp;quot;:&amp;quot;t&amp;quot;,&amp;quot;ṭ&amp;quot;:&amp;quot;t&amp;quot;,&amp;quot;ț&amp;quot;:&amp;quot;t&amp;quot;,&amp;quot;ţ&amp;quot;:&amp;quot;t&amp;quot;,&amp;quot;ṱ&amp;quot;:&amp;quot;t&amp;quot;,&amp;quot;ṯ&amp;quot;:&amp;quot;t&amp;quot;,&amp;quot;ŧ&amp;quot;:&amp;quot;t&amp;quot;,&amp;quot;ƭ&amp;quot;:&amp;quot;t&amp;quot;,&amp;quot;ʈ&amp;quot;:&amp;quot;t&amp;quot;,&amp;quot;ⱦ&amp;quot;:&amp;quot;t&amp;quot;,&amp;quot;ꞇ&amp;quot;:&amp;quot;t&amp;quot;,&amp;quot;ꜩ&amp;quot;:&amp;quot;tz&amp;quot;,&amp;quot;ⓤ&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ｕ&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ù&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ú&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;û&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ũ&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ṹ&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ū&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ṻ&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ŭ&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ü&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ǜ&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ǘ&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ǖ&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ǚ&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ủ&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ů&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ű&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ǔ&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ȕ&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ȗ&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ư&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ừ&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ứ&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ữ&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ử&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ự&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ụ&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ṳ&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ų&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ṷ&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ṵ&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ʉ&amp;quot;:&amp;quot;u&amp;quot;,&amp;quot;ⓥ&amp;quot;:&amp;quot;v&amp;quot;,&amp;quot;ｖ&amp;quot;:&amp;quot;v&amp;quot;,&amp;quot;ṽ&amp;quot;:&amp;quot;v&amp;quot;,&amp;quot;ṿ&amp;quot;:&amp;quot;v&amp;quot;,&amp;quot;ʋ&amp;quot;:&amp;quot;v&amp;quot;,&amp;quot;ꝟ&amp;quot;:&amp;quot;v&amp;quot;,&amp;quot;ʌ&amp;quot;:&amp;quot;v&amp;quot;,&amp;quot;ꝡ&amp;quot;:&amp;quot;vy&amp;quot;,&amp;quot;ⓦ&amp;quot;:&amp;quot;w&amp;quot;,&amp;quot;ｗ&amp;quot;:&amp;quot;w&amp;quot;,&amp;quot;ẁ&amp;quot;:&amp;quot;w&amp;quot;,&amp;quot;ẃ&amp;quot;:&amp;quot;w&amp;quot;,&amp;quot;ŵ&amp;quot;:&amp;quot;w&amp;quot;,&amp;quot;ẇ&amp;quot;:&amp;quot;w&amp;quot;,&amp;quot;ẅ&amp;quot;:&amp;quot;w&amp;quot;,&amp;quot;ẘ&amp;quot;:&amp;quot;w&amp;quot;,&amp;quot;ẉ&amp;quot;:&amp;quot;w&amp;quot;,&amp;quot;ⱳ&amp;quot;:&amp;quot;w&amp;quot;,&amp;quot;ⓧ&amp;quot;:&amp;quot;x&amp;quot;,&amp;quot;ｘ&amp;quot;:&amp;quot;x&amp;quot;,&amp;quot;ẋ&amp;quot;:&amp;quot;x&amp;quot;,&amp;quot;ẍ&amp;quot;:&amp;quot;x&amp;quot;,&amp;quot;ⓨ&amp;quot;:&amp;quot;y&amp;quot;,&amp;quot;ｙ&amp;quot;:&amp;quot;y&amp;quot;,&amp;quot;ỳ&amp;quot;:&amp;quot;y&amp;quot;,&amp;quot;ý&amp;quot;:&amp;quot;y&amp;quot;,&amp;quot;ŷ&amp;quot;:&amp;quot;y&amp;quot;,&amp;quot;ỹ&amp;quot;:&amp;quot;y&amp;quot;,&amp;quot;ȳ&amp;quot;:&amp;quot;y&amp;quot;,&amp;quot;ẏ&amp;quot;:&amp;quot;y&amp;quot;,&amp;quot;ÿ&amp;quot;:&amp;quot;y&amp;quot;,&amp;quot;ỷ&amp;quot;:&amp;quot;y&amp;quot;,&amp;quot;ẙ&amp;quot;:&amp;quot;y&amp;quot;,&amp;quot;ỵ&amp;quot;:&amp;quot;y&amp;quot;,&amp;quot;ƴ&amp;quot;:&amp;quot;y&amp;quot;,&amp;quot;ɏ&amp;quot;:&amp;quot;y&amp;quot;,&amp;quot;ỿ&amp;quot;:&amp;quot;y&amp;quot;,&amp;quot;ⓩ&amp;quot;:&amp;quot;z&amp;quot;,&amp;quot;ｚ&amp;quot;:&amp;quot;z&amp;quot;,&amp;quot;ź&amp;quot;:&amp;quot;z&amp;quot;,&amp;quot;ẑ&amp;quot;:&amp;quot;z&amp;quot;,&amp;quot;ż&amp;quot;:&amp;quot;z&amp;quot;,&amp;quot;ž&amp;quot;:&amp;quot;z&amp;quot;,&amp;quot;ẓ&amp;quot;:&amp;quot;z&amp;quot;,&amp;quot;ẕ&amp;quot;:&amp;quot;z&amp;quot;,&amp;quot;ƶ&amp;quot;:&amp;quot;z&amp;quot;,&amp;quot;ȥ&amp;quot;:&amp;quot;z&amp;quot;,&amp;quot;ɀ&amp;quot;:&amp;quot;z&amp;quot;,&amp;quot;ⱬ&amp;quot;:&amp;quot;z&amp;quot;,&amp;quot;ꝣ&amp;quot;:&amp;quot;z&amp;quot;,&amp;quot;Ά&amp;quot;:&amp;quot;Α&amp;quot;,&amp;quot;Έ&amp;quot;:&amp;quot;Ε&amp;quot;,&amp;quot;Ή&amp;quot;:&amp;quot;Η&amp;quot;,&amp;quot;Ί&amp;quot;:&amp;quot;Ι&amp;quot;,&amp;quot;Ϊ&amp;quot;:&amp;quot;Ι&amp;quot;,&amp;quot;Ό&amp;quot;:&amp;quot;Ο&amp;quot;,&amp;quot;Ύ&amp;quot;:&amp;quot;Υ&amp;quot;,&amp;quot;Ϋ&amp;quot;:&amp;quot;Υ&amp;quot;,&amp;quot;Ώ&amp;quot;:&amp;quot;Ω&amp;quot;,&amp;quot;ά&amp;quot;:&amp;quot;α&amp;quot;,&amp;quot;έ&amp;quot;:&amp;quot;ε&amp;quot;,&amp;quot;ή&amp;quot;:&amp;quot;η&amp;quot;,&amp;quot;ί&amp;quot;:&amp;quot;ι&amp;quot;,&amp;quot;ϊ&amp;quot;:&amp;quot;ι&amp;quot;,&amp;quot;ΐ&amp;quot;:&amp;quot;ι&amp;quot;,&amp;quot;ό&amp;quot;:&amp;quot;ο&amp;quot;,&amp;quot;ύ&amp;quot;:&amp;quot;υ&amp;quot;,&amp;quot;ϋ&amp;quot;:&amp;quot;υ&amp;quot;,&amp;quot;ΰ&amp;quot;:&amp;quot;υ&amp;quot;,&amp;quot;ώ&amp;quot;:&amp;quot;ω&amp;quot;,&amp;quot;ς&amp;quot;:&amp;quot;σ&amp;quot;,&amp;quot;’&amp;quot;:&amp;quot;&#039;&amp;quot;}}),e.define(&amp;quot;select2/data/base&amp;quot;,[&amp;quot;../utils&amp;quot;],function(r){function n(e,t){n.__super__.constructor.call(this)}return r.Extend(n,r.Observable),n.prototype.current=function(e){throw new Error(&amp;quot;The `current` method must be defined in child classes.&amp;quot;)},n.prototype.query=function(e,t){throw new Error(&amp;quot;The `query` method must be defined in child classes.&amp;quot;)},n.prototype.bind=function(e,t){},n.prototype.destroy=function(){},n.prototype.generateResultId=function(e,t){var n=e.id+&amp;quot;-result-&amp;quot;;return n+=r.generateChars(4),null!=t.id?n+=&amp;quot;-&amp;quot;+t.id.toString():n+=&amp;quot;-&amp;quot;+r.generateChars(4),n},n}),e.define(&amp;quot;select2/data/select&amp;quot;,[&amp;quot;./base&amp;quot;,&amp;quot;../utils&amp;quot;,&amp;quot;jquery&amp;quot;],function(e,a,l){function n(e,t){this.$element=e,this.options=t,n.__super__.constructor.call(this)}return a.Extend(n,e),n.prototype.current=function(e){var n=[],r=this;this.$element.find(&amp;quot;:selected&amp;quot;).each(function(){var e=l(this),t=r.item(e);n.push(t)}),e(n)},n.prototype.select=function(i){var o=this;if(i.selected=!0,l(i.element).is(&amp;quot;option&amp;quot;))return i.element.selected=!0,void this.$element.trigger(&amp;quot;change&amp;quot;);if(this.$element.prop(&amp;quot;multiple&amp;quot;))this.current(function(e){var t=[];(i=[i]).push.apply(i,e);for(var n=0;n&amp;lt;i.length;n++){var r=i[n].id;-1===l.inArray(r,t)&amp;amp;&amp;amp;t.push(r)}o.$element.val(t),o.$element.trigger(&amp;quot;change&amp;quot;)});else{var e=i.id;this.$element.val(e),this.$element.trigger(&amp;quot;change&amp;quot;)}},n.prototype.unselect=function(i){var o=this;if(this.$element.prop(&amp;quot;multiple&amp;quot;)){if(i.selected=!1,l(i.element).is(&amp;quot;option&amp;quot;))return i.element.selected=!1,void this.$element.trigger(&amp;quot;change&amp;quot;);this.current(function(e){for(var t=[],n=0;n&amp;lt;e.length;n++){var r=e[n].id;r!==i.id&amp;amp;&amp;amp;-1===l.inArray(r,t)&amp;amp;&amp;amp;t.push(r)}o.$element.val(t),o.$element.trigger(&amp;quot;change&amp;quot;)})}},n.prototype.bind=function(e,t){var n=this;(this.container=e).on(&amp;quot;select&amp;quot;,function(e){n.select(e.data)}),e.on(&amp;quot;unselect&amp;quot;,function(e){n.unselect(e.data)})},n.prototype.destroy=function(){this.$element.find(&amp;quot;*&amp;quot;).each(function(){a.RemoveData(this)})},n.prototype.query=function(r,e){var i=[],o=this;this.$element.children().each(function(){var e=l(this);if(e.is(&amp;quot;option&amp;quot;)||e.is(&amp;quot;optgroup&amp;quot;)){var t=o.item(e),n=o.matches(r,t);null!==n&amp;amp;&amp;amp;i.push(n)}}),e({results:i})},n.prototype.addOptions=function(e){a.appendMany(this.$element,e)},n.prototype.option=function(e){var t;e.children?(t=document.createElement(&amp;quot;optgroup&amp;quot;)).label=e.text:void 0!==(t=document.createElement(&amp;quot;option&amp;quot;)).textContent?t.textContent=e.text:t.innerText=e.text,void 0!==e.id&amp;amp;&amp;amp;(t.value=e.id),e.disabled&amp;amp;&amp;amp;(t.disabled=!0),e.selected&amp;amp;&amp;amp;(t.selected=!0),e.title&amp;amp;&amp;amp;(t.title=e.title);var n=l(t),r=this._normalizeItem(e);return r.element=t,a.StoreData(t,&amp;quot;data&amp;quot;,r),n},n.prototype.item=function(e){var t={};if(null!=(t=a.GetData(e[0],&amp;quot;data&amp;quot;)))return t;if(e.is(&amp;quot;option&amp;quot;))t={id:e.val(),text:e.text(),disabled:e.prop(&amp;quot;disabled&amp;quot;),selected:e.prop(&amp;quot;selected&amp;quot;),title:e.prop(&amp;quot;title&amp;quot;)};else if(e.is(&amp;quot;optgroup&amp;quot;)){t={text:e.prop(&amp;quot;label&amp;quot;),children:[],title:e.prop(&amp;quot;title&amp;quot;)};for(var n=e.children(&amp;quot;option&amp;quot;),r=[],i=0;i&amp;lt;n.length;i++){var o=l(n[i]),s=this.item(o);r.push(s)}t.children=r}return(t=this._normalizeItem(t)).element=e[0],a.StoreData(e[0],&amp;quot;data&amp;quot;,t),t},n.prototype._normalizeItem=function(e){e!==Object(e)&amp;amp;&amp;amp;(e={id:e,text:e});return null!=(e=l.extend({},{text:&amp;quot;&amp;quot;},e)).id&amp;amp;&amp;amp;(e.id=e.id.toString()),null!=e.text&amp;amp;&amp;amp;(e.text=e.text.toString()),null==e._resultId&amp;amp;&amp;amp;e.id&amp;amp;&amp;amp;null!=this.container&amp;amp;&amp;amp;(e._resultId=this.generateResultId(this.container,e)),l.extend({},{selected:!1,disabled:!1},e)},n.prototype.matches=function(e,t){return this.options.get(&amp;quot;matcher&amp;quot;)(e,t)},n}),e.define(&amp;quot;select2/data/array&amp;quot;,[&amp;quot;./select&amp;quot;,&amp;quot;../utils&amp;quot;,&amp;quot;jquery&amp;quot;],function(e,f,g){function r(e,t){this._dataToConvert=t.get(&amp;quot;data&amp;quot;)||[],r.__super__.constructor.call(this,e,t)}return f.Extend(r,e),r.prototype.bind=function(e,t){r.__super__.bind.call(this,e,t),this.addOptions(this.convertToOptions(this._dataToConvert))},r.prototype.select=function(n){var e=this.$element.find(&amp;quot;option&amp;quot;).filter(function(e,t){return t.value==n.id.toString()});0===e.length&amp;amp;&amp;amp;(e=this.option(n),this.addOptions(e)),r.__super__.select.call(this,n)},r.prototype.convertToOptions=function(e){var t=this,n=this.$element.find(&amp;quot;option&amp;quot;),r=n.map(function(){return t.item(g(this)).id}).get(),i=[];function o(e){return function(){return g(this).val()==e.id}}for(var s=0;s&amp;lt;e.length;s++){var a=this._normalizeItem(e[s]);if(0&amp;lt;=g.inArray(a.id,r)){var l=n.filter(o(a)),c=this.item(l),u=g.extend(!0,{},a,c),d=this.option(u);l.replaceWith(d)}else{var p=this.option(a);if(a.children){var h=this.convertToOptions(a.children);f.appendMany(p,h)}i.push(p)}}return i},r}),e.define(&amp;quot;select2/data/ajax&amp;quot;,[&amp;quot;./array&amp;quot;,&amp;quot;../utils&amp;quot;,&amp;quot;jquery&amp;quot;],function(e,t,o){function n(e,t){this.ajaxOptions=this._applyDefaults(t.get(&amp;quot;ajax&amp;quot;)),null!=this.ajaxOptions.processResults&amp;amp;&amp;amp;(this.processResults=this.ajaxOptions.processResults),n.__super__.constructor.call(this,e,t)}return t.Extend(n,e),n.prototype._applyDefaults=function(e){var t={data:function(e){return o.extend({},e,{q:e.term})},transport:function(e,t,n){var r=o.ajax(e);return r.then(t),r.fail(n),r}};return o.extend({},t,e,!0)},n.prototype.processResults=function(e){return e},n.prototype.query=function(n,r){var i=this;null!=this._request&amp;amp;&amp;amp;(o.isFunction(this._request.abort)&amp;amp;&amp;amp;this._request.abort(),this._request=null);var t=o.extend({type:&amp;quot;GET&amp;quot;},this.ajaxOptions);function e(){var e=t.transport(t,function(e){var t=i.processResults(e,n);i.options.get(&amp;quot;debug&amp;quot;)&amp;amp;&amp;amp;window.console&amp;amp;&amp;amp;console.error&amp;amp;&amp;amp;(t&amp;amp;&amp;amp;t.results&amp;amp;&amp;amp;o.isArray(t.results)||console.error(&amp;quot;Select2: The AJAX results did not return an array in the `results` key of the response.&amp;quot;)),r(t)},function(){&amp;quot;status&amp;quot;in e&amp;amp;&amp;amp;(0===e.status||&amp;quot;0&amp;quot;===e.status)||i.trigger(&amp;quot;results:message&amp;quot;,{message:&amp;quot;errorLoading&amp;quot;})});i._request=e}&amp;quot;function&amp;quot;==typeof t.url&amp;amp;&amp;amp;(t.url=t.url.call(this.$element,n)),&amp;quot;function&amp;quot;==typeof t.data&amp;amp;&amp;amp;(t.data=t.data.call(this.$element,n)),this.ajaxOptions.delay&amp;amp;&amp;amp;null!=n.term?(this._queryTimeout&amp;amp;&amp;amp;window.clearTimeout(this._queryTimeout),this._queryTimeout=window.setTimeout(e,this.ajaxOptions.delay)):e()},n}),e.define(&amp;quot;select2/data/tags&amp;quot;,[&amp;quot;jquery&amp;quot;],function(u){function e(e,t,n){var r=n.get(&amp;quot;tags&amp;quot;),i=n.get(&amp;quot;createTag&amp;quot;);void 0!==i&amp;amp;&amp;amp;(this.createTag=i);var o=n.get(&amp;quot;insertTag&amp;quot;);if(void 0!==o&amp;amp;&amp;amp;(this.insertTag=o),e.call(this,t,n),u.isArray(r))for(var s=0;s&amp;lt;r.length;s++){var a=r[s],l=this._normalizeItem(a),c=this.option(l);this.$element.append(c)}}return e.prototype.query=function(e,c,u){var d=this;this._removeOldTags(),null!=c.term&amp;amp;&amp;amp;null==c.page?e.call(this,c,function e(t,n){for(var r=t.results,i=0;i&amp;lt;r.length;i++){var o=r[i],s=null!=o.children&amp;amp;&amp;amp;!e({results:o.children},!0);if((o.text||&amp;quot;&amp;quot;).toUpperCase()===(c.term||&amp;quot;&amp;quot;).toUpperCase()||s)return!n&amp;amp;&amp;amp;(t.data=r,void u(t))}if(n)return!0;var a=d.createTag(c);if(null!=a){var l=d.option(a);l.attr(&amp;quot;data-select2-tag&amp;quot;,!0),d.addOptions([l]),d.insertTag(r,a)}t.results=r,u(t)}):e.call(this,c,u)},e.prototype.createTag=function(e,t){var n=u.trim(t.term);return&amp;quot;&amp;quot;===n?null:{id:n,text:n}},e.prototype.insertTag=function(e,t,n){t.unshift(n)},e.prototype._removeOldTags=function(e){this.$element.find(&amp;quot;option[data-select2-tag]&amp;quot;).each(function(){this.selected||u(this).remove()})},e}),e.define(&amp;quot;select2/data/tokenizer&amp;quot;,[&amp;quot;jquery&amp;quot;],function(d){function e(e,t,n){var r=n.get(&amp;quot;tokenizer&amp;quot;);void 0!==r&amp;amp;&amp;amp;(this.tokenizer=r),e.call(this,t,n)}return e.prototype.bind=function(e,t,n){e.call(this,t,n),this.$search=t.dropdown.$search||t.selection.$search||n.find(&amp;quot;.select2-search__field&amp;quot;)},e.prototype.query=function(e,t,n){var r=this;t.term=t.term||&amp;quot;&amp;quot;;var i=this.tokenizer(t,this.options,function(e){var t=r._normalizeItem(e);if(!r.$element.find(&amp;quot;option&amp;quot;).filter(function(){return d(this).val()===t.id}).length){var n=r.option(t);n.attr(&amp;quot;data-select2-tag&amp;quot;,!0),r._removeOldTags(),r.addOptions([n])}!function(e){r.trigger(&amp;quot;select&amp;quot;,{data:e})}(t)});i.term!==t.term&amp;amp;&amp;amp;(this.$search.length&amp;amp;&amp;amp;(this.$search.val(i.term),this.$search.trigger(&amp;quot;focus&amp;quot;)),t.term=i.term),e.call(this,t,n)},e.prototype.tokenizer=function(e,t,n,r){for(var i=n.get(&amp;quot;tokenSeparators&amp;quot;)||[],o=t.term,s=0,a=this.createTag||function(e){return{id:e.term,text:e.term}};s&amp;lt;o.length;){var l=o[s];if(-1!==d.inArray(l,i)){var c=o.substr(0,s),u=a(d.extend({},t,{term:c}));null!=u?(r(u),o=o.substr(s+1)||&amp;quot;&amp;quot;,s=0):s++}else s++}return{term:o}},e}),e.define(&amp;quot;select2/data/minimumInputLength&amp;quot;,[],function(){function e(e,t,n){this.minimumInputLength=n.get(&amp;quot;minimumInputLength&amp;quot;),e.call(this,t,n)}return e.prototype.query=function(e,t,n){t.term=t.term||&amp;quot;&amp;quot;,t.term.length&amp;lt;this.minimumInputLength?this.trigger(&amp;quot;results:message&amp;quot;,{message:&amp;quot;inputTooShort&amp;quot;,args:{minimum:this.minimumInputLength,input:t.term,params:t}}):e.call(this,t,n)},e}),e.define(&amp;quot;select2/data/maximumInputLength&amp;quot;,[],function(){function e(e,t,n){this.maximumInputLength=n.get(&amp;quot;maximumInputLength&amp;quot;),e.call(this,t,n)}return e.prototype.query=function(e,t,n){t.term=t.term||&amp;quot;&amp;quot;,0&amp;lt;this.maximumInputLength&amp;amp;&amp;amp;t.term.length&amp;gt;this.maximumInputLength?this.trigger(&amp;quot;results:message&amp;quot;,{message:&amp;quot;inputTooLong&amp;quot;,args:{maximum:this.maximumInputLength,input:t.term,params:t}}):e.call(this,t,n)},e}),e.define(&amp;quot;select2/data/maximumSelectionLength&amp;quot;,[],function(){function e(e,t,n){this.maximumSelectionLength=n.get(&amp;quot;maximumSelectionLength&amp;quot;),e.call(this,t,n)}return e.prototype.bind=function(e,t,n){var r=this;e.call(this,t,n),t.on(&amp;quot;select&amp;quot;,function(){r._checkIfMaximumSelected()})},e.prototype.query=function(e,t,n){var r=this;this._checkIfMaximumSelected(function(){e.call(r,t,n)})},e.prototype._checkIfMaximumSelected=function(e,n){var r=this;this.current(function(e){var t=null!=e?e.length:0;0&amp;lt;r.maximumSelectionLength&amp;amp;&amp;amp;t&amp;gt;=r.maximumSelectionLength?r.trigger(&amp;quot;results:message&amp;quot;,{message:&amp;quot;maximumSelected&amp;quot;,args:{maximum:r.maximumSelectionLength}}):n&amp;amp;&amp;amp;n()})},e}),e.define(&amp;quot;select2/dropdown&amp;quot;,[&amp;quot;jquery&amp;quot;,&amp;quot;./utils&amp;quot;],function(t,e){function n(e,t){this.$element=e,this.options=t,n.__super__.constructor.call(this)}return e.Extend(n,e.Observable),n.prototype.render=function(){var e=t(&#039;&amp;lt;span class=&amp;quot;select2-dropdown&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;select2-results&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039;);return e.attr(&amp;quot;dir&amp;quot;,this.options.get(&amp;quot;dir&amp;quot;)),this.$dropdown=e},n.prototype.bind=function(){},n.prototype.position=function(e,t){},n.prototype.destroy=function(){this.$dropdown.remove()},n}),e.define(&amp;quot;select2/dropdown/search&amp;quot;,[&amp;quot;jquery&amp;quot;,&amp;quot;../utils&amp;quot;],function(o,e){function t(){}return t.prototype.render=function(e){var t=e.call(this),n=o(&#039;&amp;lt;span class=&amp;quot;select2-search select2-search--dropdown&amp;quot;&amp;gt;&amp;lt;input class=&amp;quot;select2-search__field&amp;quot; type=&amp;quot;search&amp;quot; tabindex=&amp;quot;-1&amp;quot; autocomplete=&amp;quot;off&amp;quot; autocorrect=&amp;quot;off&amp;quot; autocapitalize=&amp;quot;none&amp;quot; spellcheck=&amp;quot;false&amp;quot; role=&amp;quot;searchbox&amp;quot; aria-autocomplete=&amp;quot;list&amp;quot; /&amp;gt;&amp;lt;/span&amp;gt;&#039;);return this.$searchContainer=n,this.$search=n.find(&amp;quot;input&amp;quot;),t.prepend(n),t},t.prototype.bind=function(e,t,n){var r=this,i=t.id+&amp;quot;-results&amp;quot;;e.call(this,t,n),this.$search.on(&amp;quot;keydown&amp;quot;,function(e){r.trigger(&amp;quot;keypress&amp;quot;,e),r._keyUpPrevented=e.isDefaultPrevented()}),this.$search.on(&amp;quot;input&amp;quot;,function(e){o(this).off(&amp;quot;keyup&amp;quot;)}),this.$search.on(&amp;quot;keyup input&amp;quot;,function(e){r.handleSearch(e)}),t.on(&amp;quot;open&amp;quot;,function(){r.$search.attr(&amp;quot;tabindex&amp;quot;,0),r.$search.attr(&amp;quot;aria-controls&amp;quot;,i),r.$search.trigger(&amp;quot;focus&amp;quot;),window.setTimeout(function(){r.$search.trigger(&amp;quot;focus&amp;quot;)},0)}),t.on(&amp;quot;close&amp;quot;,function(){r.$search.attr(&amp;quot;tabindex&amp;quot;,-1),r.$search.removeAttr(&amp;quot;aria-controls&amp;quot;),r.$search.removeAttr(&amp;quot;aria-activedescendant&amp;quot;),r.$search.val(&amp;quot;&amp;quot;),r.$search.trigger(&amp;quot;blur&amp;quot;)}),t.on(&amp;quot;focus&amp;quot;,function(){t.isOpen()||r.$search.trigger(&amp;quot;focus&amp;quot;)}),t.on(&amp;quot;results:all&amp;quot;,function(e){null!=e.query.term&amp;amp;&amp;amp;&amp;quot;&amp;quot;!==e.query.term||(r.showSearch(e)?r.$searchContainer.removeClass(&amp;quot;select2-search--hide&amp;quot;):r.$searchContainer.addClass(&amp;quot;select2-search--hide&amp;quot;))}),t.on(&amp;quot;results:focus&amp;quot;,function(e){e.data._resultId?r.$search.attr(&amp;quot;aria-activedescendant&amp;quot;,e.data._resultId):r.$search.removeAttr(&amp;quot;aria-activedescendant&amp;quot;)})},t.prototype.handleSearch=function(e){if(!this._keyUpPrevented){var t=this.$search.val();this.trigger(&amp;quot;query&amp;quot;,{term:t})}this._keyUpPrevented=!1},t.prototype.showSearch=function(e,t){return!0},t}),e.define(&amp;quot;select2/dropdown/hidePlaceholder&amp;quot;,[],function(){function e(e,t,n,r){this.placeholder=this.normalizePlaceholder(n.get(&amp;quot;placeholder&amp;quot;)),e.call(this,t,n,r)}return e.prototype.append=function(e,t){t.results=this.removePlaceholder(t.results),e.call(this,t)},e.prototype.normalizePlaceholder=function(e,t){return&amp;quot;string&amp;quot;==typeof t&amp;amp;&amp;amp;(t={id:&amp;quot;&amp;quot;,text:t}),t},e.prototype.removePlaceholder=function(e,t){for(var n=t.slice(0),r=t.length-1;0&amp;lt;=r;r--){var i=t[r];this.placeholder.id===i.id&amp;amp;&amp;amp;n.splice(r,1)}return n},e}),e.define(&amp;quot;select2/dropdown/infiniteScroll&amp;quot;,[&amp;quot;jquery&amp;quot;],function(n){function e(e,t,n,r){this.lastParams={},e.call(this,t,n,r),this.$loadingMore=this.createLoadingMore(),this.loading=!1}return e.prototype.append=function(e,t){this.$loadingMore.remove(),this.loading=!1,e.call(this,t),this.showLoadingMore(t)&amp;amp;&amp;amp;(this.$results.append(this.$loadingMore),this.loadMoreIfNeeded())},e.prototype.bind=function(e,t,n){var r=this;e.call(this,t,n),t.on(&amp;quot;query&amp;quot;,function(e){r.lastParams=e,r.loading=!0}),t.on(&amp;quot;query:append&amp;quot;,function(e){r.lastParams=e,r.loading=!0}),this.$results.on(&amp;quot;scroll&amp;quot;,this.loadMoreIfNeeded.bind(this))},e.prototype.loadMoreIfNeeded=function(){var e=n.contains(document.documentElement,this.$loadingMore[0]);if(!this.loading&amp;amp;&amp;amp;e){var t=this.$results.offset().top+this.$results.outerHeight(!1);this.$loadingMore.offset().top+this.$loadingMore.outerHeight(!1)&amp;lt;=t+50&amp;amp;&amp;amp;this.loadMore()}},e.prototype.loadMore=function(){this.loading=!0;var e=n.extend({},{page:1},this.lastParams);e.page++,this.trigger(&amp;quot;query:append&amp;quot;,e)},e.prototype.showLoadingMore=function(e,t){return t.pagination&amp;amp;&amp;amp;t.pagination.more},e.prototype.createLoadingMore=function(){var e=n(&#039;&amp;lt;li class=&amp;quot;select2-results__option select2-results__option--load-more&amp;quot;role=&amp;quot;option&amp;quot; aria-disabled=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;&#039;),t=this.options.get(&amp;quot;translations&amp;quot;).get(&amp;quot;loadingMore&amp;quot;);return e.html(t(this.lastParams)),e},e}),e.define(&amp;quot;select2/dropdown/attachBody&amp;quot;,[&amp;quot;jquery&amp;quot;,&amp;quot;../utils&amp;quot;],function(f,a){function e(e,t,n){this.$dropdownParent=f(n.get(&amp;quot;dropdownParent&amp;quot;)||document.body),e.call(this,t,n)}return e.prototype.bind=function(e,t,n){var r=this;e.call(this,t,n),t.on(&amp;quot;open&amp;quot;,function(){r._showDropdown(),r._attachPositioningHandler(t),r._bindContainerResultHandlers(t)}),t.on(&amp;quot;close&amp;quot;,function(){r._hideDropdown(),r._detachPositioningHandler(t)}),this.$dropdownContainer.on(&amp;quot;mousedown&amp;quot;,function(e){e.stopPropagation()})},e.prototype.destroy=function(e){e.call(this),this.$dropdownContainer.remove()},e.prototype.position=function(e,t,n){t.attr(&amp;quot;class&amp;quot;,n.attr(&amp;quot;class&amp;quot;)),t.removeClass(&amp;quot;select2&amp;quot;),t.addClass(&amp;quot;select2-container--open&amp;quot;),t.css({position:&amp;quot;absolute&amp;quot;,top:-999999}),this.$container=n},e.prototype.render=function(e){var t=f(&amp;quot;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;),n=e.call(this);return t.append(n),this.$dropdownContainer=t},e.prototype._hideDropdown=function(e){this.$dropdownContainer.detach()},e.prototype._bindContainerResultHandlers=function(e,t){if(!this._containerResultsHandlersBound){var n=this;t.on(&amp;quot;results:all&amp;quot;,function(){n._positionDropdown(),n._resizeDropdown()}),t.on(&amp;quot;results:append&amp;quot;,function(){n._positionDropdown(),n._resizeDropdown()}),t.on(&amp;quot;results:message&amp;quot;,function(){n._positionDropdown(),n._resizeDropdown()}),t.on(&amp;quot;select&amp;quot;,function(){n._positionDropdown(),n._resizeDropdown()}),t.on(&amp;quot;unselect&amp;quot;,function(){n._positionDropdown(),n._resizeDropdown()}),this._containerResultsHandlersBound=!0}},e.prototype._attachPositioningHandler=function(e,t){var n=this,r=&amp;quot;scroll.select2.&amp;quot;+t.id,i=&amp;quot;resize.select2.&amp;quot;+t.id,o=&amp;quot;orientationchange.select2.&amp;quot;+t.id,s=this.$container.parents().filter(a.hasScroll);s.each(function(){a.StoreData(this,&amp;quot;select2-scroll-position&amp;quot;,{x:f(this).scrollLeft(),y:f(this).scrollTop()})}),s.on(r,function(e){var t=a.GetData(this,&amp;quot;select2-scroll-position&amp;quot;);f(this).scrollTop(t.y)}),f(window).on(r+&amp;quot; &amp;quot;+i+&amp;quot; &amp;quot;+o,function(e){n._positionDropdown(),n._resizeDropdown()})},e.prototype._detachPositioningHandler=function(e,t){var n=&amp;quot;scroll.select2.&amp;quot;+t.id,r=&amp;quot;resize.select2.&amp;quot;+t.id,i=&amp;quot;orientationchange.select2.&amp;quot;+t.id;this.$container.parents().filter(a.hasScroll).off(n),f(window).off(n+&amp;quot; &amp;quot;+r+&amp;quot; &amp;quot;+i)},e.prototype._positionDropdown=function(){var e=f(window),t=this.$dropdown.hasClass(&amp;quot;select2-dropdown--above&amp;quot;),n=this.$dropdown.hasClass(&amp;quot;select2-dropdown--below&amp;quot;),r=null,i=this.$container.offset();i.bottom=i.top+this.$container.outerHeight(!1);var o={height:this.$container.outerHeight(!1)};o.top=i.top,o.bottom=i.top+o.height;var s=this.$dropdown.outerHeight(!1),a=e.scrollTop(),l=e.scrollTop()+e.height(),c=a&amp;lt;i.top-s,u=l&amp;gt;i.bottom+s,d={left:i.left,top:o.bottom},p=this.$dropdownParent;&amp;quot;static&amp;quot;===p.css(&amp;quot;position&amp;quot;)&amp;amp;&amp;amp;(p=p.offsetParent());var h={top:0,left:0};(f.contains(document.body,p[0])||p[0].isConnected)&amp;amp;&amp;amp;(h=p.offset()),d.top-=h.top,d.left-=h.left,t||n||(r=&amp;quot;below&amp;quot;),u||!c||t?!c&amp;amp;&amp;amp;u&amp;amp;&amp;amp;t&amp;amp;&amp;amp;(r=&amp;quot;below&amp;quot;):r=&amp;quot;above&amp;quot;,(&amp;quot;above&amp;quot;==r||t&amp;amp;&amp;amp;&amp;quot;below&amp;quot;!==r)&amp;amp;&amp;amp;(d.top=o.top-h.top-s),null!=r&amp;amp;&amp;amp;(this.$dropdown.removeClass(&amp;quot;select2-dropdown--below select2-dropdown--above&amp;quot;).addClass(&amp;quot;select2-dropdown--&amp;quot;+r),this.$container.removeClass(&amp;quot;select2-container--below select2-container--above&amp;quot;).addClass(&amp;quot;select2-container--&amp;quot;+r)),this.$dropdownContainer.css(d)},e.prototype._resizeDropdown=function(){var e={width:this.$container.outerWidth(!1)+&amp;quot;px&amp;quot;};this.options.get(&amp;quot;dropdownAutoWidth&amp;quot;)&amp;amp;&amp;amp;(e.minWidth=e.width,e.position=&amp;quot;relative&amp;quot;,e.width=&amp;quot;auto&amp;quot;),this.$dropdown.css(e)},e.prototype._showDropdown=function(e){this.$dropdownContainer.appendTo(this.$dropdownParent),this._positionDropdown(),this._resizeDropdown()},e}),e.define(&amp;quot;select2/dropdown/minimumResultsForSearch&amp;quot;,[],function(){function e(e,t,n,r){this.minimumResultsForSearch=n.get(&amp;quot;minimumResultsForSearch&amp;quot;),this.minimumResultsForSearch&amp;lt;0&amp;amp;&amp;amp;(this.minimumResultsForSearch=1/0),e.call(this,t,n,r)}return e.prototype.showSearch=function(e,t){return!(function e(t){for(var n=0,r=0;r&amp;lt;t.length;r++){var i=t[r];i.children?n+=e(i.children):n++}return n}(t.data.results)&amp;lt;this.minimumResultsForSearch)&amp;amp;&amp;amp;e.call(this,t)},e}),e.define(&amp;quot;select2/dropdown/selectOnClose&amp;quot;,[&amp;quot;../utils&amp;quot;],function(o){function e(){}return e.prototype.bind=function(e,t,n){var r=this;e.call(this,t,n),t.on(&amp;quot;close&amp;quot;,function(e){r._handleSelectOnClose(e)})},e.prototype._handleSelectOnClose=function(e,t){if(t&amp;amp;&amp;amp;null!=t.originalSelect2Event){var n=t.originalSelect2Event;if(&amp;quot;select&amp;quot;===n._type||&amp;quot;unselect&amp;quot;===n._type)return}var r=this.getHighlightedResults();if(!(r.length&amp;lt;1)){var i=o.GetData(r[0],&amp;quot;data&amp;quot;);null!=i.element&amp;amp;&amp;amp;i.element.selected||null==i.element&amp;amp;&amp;amp;i.selected||this.trigger(&amp;quot;select&amp;quot;,{data:i})}},e}),e.define(&amp;quot;select2/dropdown/closeOnSelect&amp;quot;,[],function(){function e(){}return e.prototype.bind=function(e,t,n){var r=this;e.call(this,t,n),t.on(&amp;quot;select&amp;quot;,function(e){r._selectTriggered(e)}),t.on(&amp;quot;unselect&amp;quot;,function(e){r._selectTriggered(e)})},e.prototype._selectTriggered=function(e,t){var n=t.originalEvent;n&amp;amp;&amp;amp;(n.ctrlKey||n.metaKey)||this.trigger(&amp;quot;close&amp;quot;,{originalEvent:n,originalSelect2Event:t})},e}),e.define(&amp;quot;select2/i18n/en&amp;quot;,[],function(){return{errorLoading:function(){return&amp;quot;The results could not be loaded.&amp;quot;},inputTooLong:function(e){var t=e.input.length-e.maximum,n=&amp;quot;Please delete &amp;quot;+t+&amp;quot; character&amp;quot;;return 1!=t&amp;amp;&amp;amp;(n+=&amp;quot;s&amp;quot;),n},inputTooShort:function(e){return&amp;quot;Please enter &amp;quot;+(e.minimum-e.input.length)+&amp;quot; or more characters&amp;quot;},loadingMore:function(){return&amp;quot;Loading more results…&amp;quot;},maximumSelected:function(e){var t=&amp;quot;You can only select &amp;quot;+e.maximum+&amp;quot; item&amp;quot;;return 1!=e.maximum&amp;amp;&amp;amp;(t+=&amp;quot;s&amp;quot;),t},noResults:function(){return&amp;quot;No results found&amp;quot;},searching:function(){return&amp;quot;Searching…&amp;quot;},removeAllItems:function(){return&amp;quot;Remove all items&amp;quot;}}}),e.define(&amp;quot;select2/defaults&amp;quot;,[&amp;quot;jquery&amp;quot;,&amp;quot;require&amp;quot;,&amp;quot;./results&amp;quot;,&amp;quot;./selection/single&amp;quot;,&amp;quot;./selection/multiple&amp;quot;,&amp;quot;./selection/placeholder&amp;quot;,&amp;quot;./selection/allowClear&amp;quot;,&amp;quot;./selection/search&amp;quot;,&amp;quot;./selection/eventRelay&amp;quot;,&amp;quot;./utils&amp;quot;,&amp;quot;./translation&amp;quot;,&amp;quot;./diacritics&amp;quot;,&amp;quot;./data/select&amp;quot;,&amp;quot;./data/array&amp;quot;,&amp;quot;./data/ajax&amp;quot;,&amp;quot;./data/tags&amp;quot;,&amp;quot;./data/tokenizer&amp;quot;,&amp;quot;./data/minimumInputLength&amp;quot;,&amp;quot;./data/maximumInputLength&amp;quot;,&amp;quot;./data/maximumSelectionLength&amp;quot;,&amp;quot;./dropdown&amp;quot;,&amp;quot;./dropdown/search&amp;quot;,&amp;quot;./dropdown/hidePlaceholder&amp;quot;,&amp;quot;./dropdown/infiniteScroll&amp;quot;,&amp;quot;./dropdown/attachBody&amp;quot;,&amp;quot;./dropdown/minimumResultsForSearch&amp;quot;,&amp;quot;./dropdown/selectOnClose&amp;quot;,&amp;quot;./dropdown/closeOnSelect&amp;quot;,&amp;quot;./i18n/en&amp;quot;],function(c,u,d,p,h,f,g,m,v,y,s,t,_,$,w,b,A,x,D,S,E,C,O,T,q,L,I,j,e){function n(){this.reset()}return n.prototype.apply=function(e){if(null==(e=c.extend(!0,{},this.defaults,e)).dataAdapter){if(null!=e.ajax?e.dataAdapter=w:null!=e.data?e.dataAdapter=$:e.dataAdapter=_,0&amp;lt;e.minimumInputLength&amp;amp;&amp;amp;(e.dataAdapter=y.Decorate(e.dataAdapter,x)),0&amp;lt;e.maximumInputLength&amp;amp;&amp;amp;(e.dataAdapter=y.Decorate(e.dataAdapter,D)),0&amp;lt;e.maximumSelectionLength&amp;amp;&amp;amp;(e.dataAdapter=y.Decorate(e.dataAdapter,S)),e.tags&amp;amp;&amp;amp;(e.dataAdapter=y.Decorate(e.dataAdapter,b)),null==e.tokenSeparators&amp;amp;&amp;amp;null==e.tokenizer||(e.dataAdapter=y.Decorate(e.dataAdapter,A)),null!=e.query){var t=u(e.amdBase+&amp;quot;compat/query&amp;quot;);e.dataAdapter=y.Decorate(e.dataAdapter,t)}if(null!=e.initSelection){var n=u(e.amdBase+&amp;quot;compat/initSelection&amp;quot;);e.dataAdapter=y.Decorate(e.dataAdapter,n)}}if(null==e.resultsAdapter&amp;amp;&amp;amp;(e.resultsAdapter=d,null!=e.ajax&amp;amp;&amp;amp;(e.resultsAdapter=y.Decorate(e.resultsAdapter,T)),null!=e.placeholder&amp;amp;&amp;amp;(e.resultsAdapter=y.Decorate(e.resultsAdapter,O)),e.selectOnClose&amp;amp;&amp;amp;(e.resultsAdapter=y.Decorate(e.resultsAdapter,I))),null==e.dropdownAdapter){if(e.multiple)e.dropdownAdapter=E;else{var r=y.Decorate(E,C);e.dropdownAdapter=r}if(0!==e.minimumResultsForSearch&amp;amp;&amp;amp;(e.dropdownAdapter=y.Decorate(e.dropdownAdapter,L)),e.closeOnSelect&amp;amp;&amp;amp;(e.dropdownAdapter=y.Decorate(e.dropdownAdapter,j)),null!=e.dropdownCssClass||null!=e.dropdownCss||null!=e.adaptDropdownCssClass){var i=u(e.amdBase+&amp;quot;compat/dropdownCss&amp;quot;);e.dropdownAdapter=y.Decorate(e.dropdownAdapter,i)}e.dropdownAdapter=y.Decorate(e.dropdownAdapter,q)}if(null==e.selectionAdapter){if(e.multiple?e.selectionAdapter=h:e.selectionAdapter=p,null!=e.placeholder&amp;amp;&amp;amp;(e.selectionAdapter=y.Decorate(e.selectionAdapter,f)),e.allowClear&amp;amp;&amp;amp;(e.selectionAdapter=y.Decorate(e.selectionAdapter,g)),e.multiple&amp;amp;&amp;amp;(e.selectionAdapter=y.Decorate(e.selectionAdapter,m)),null!=e.containerCssClass||null!=e.containerCss||null!=e.adaptContainerCssClass){var o=u(e.amdBase+&amp;quot;compat/containerCss&amp;quot;);e.selectionAdapter=y.Decorate(e.selectionAdapter,o)}e.selectionAdapter=y.Decorate(e.selectionAdapter,v)}e.language=this._resolveLanguage(e.language),e.language.push(&amp;quot;en&amp;quot;);for(var s=[],a=0;a&amp;lt;e.language.length;a++){var l=e.language[a];-1===s.indexOf(l)&amp;amp;&amp;amp;s.push(l)}return e.language=s,e.translations=this._processTranslations(e.language,e.debug),e},n.prototype.reset=function(){function a(e){return e.replace(/[^\u0000-\u007E]/g,function(e){return t[e]||e})}this.defaults={amdBase:&amp;quot;./&amp;quot;,amdLanguageBase:&amp;quot;./i18n/&amp;quot;,closeOnSelect:!0,debug:!1,dropdownAutoWidth:!1,escapeMarkup:y.escapeMarkup,language:{},matcher:function e(t,n){if(&amp;quot;&amp;quot;===c.trim(t.term))return n;if(n.children&amp;amp;&amp;amp;0&amp;lt;n.children.length){for(var r=c.extend(!0,{},n),i=n.children.length-1;0&amp;lt;=i;i--)null==e(t,n.children[i])&amp;amp;&amp;amp;r.children.splice(i,1);return 0&amp;lt;r.children.length?r:e(t,r)}var o=a(n.text).toUpperCase(),s=a(t.term).toUpperCase();return-1&amp;lt;o.indexOf(s)?n:null},minimumInputLength:0,maximumInputLength:0,maximumSelectionLength:0,minimumResultsForSearch:0,selectOnClose:!1,scrollAfterSelect:!1,sorter:function(e){return e},templateResult:function(e){return e.text},templateSelection:function(e){return e.text},theme:&amp;quot;default&amp;quot;,width:&amp;quot;resolve&amp;quot;}},n.prototype.applyFromElement=function(e,t){var n=e.language,r=this.defaults.language,i=t.prop(&amp;quot;lang&amp;quot;),o=t.closest(&amp;quot;[lang]&amp;quot;).prop(&amp;quot;lang&amp;quot;),s=Array.prototype.concat.call(this._resolveLanguage(i),this._resolveLanguage(n),this._resolveLanguage(r),this._resolveLanguage(o));return e.language=s,e},n.prototype._resolveLanguage=function(e){if(!e)return[];if(c.isEmptyObject(e))return[];if(c.isPlainObject(e))return[e];var t;t=c.isArray(e)?e:[e];for(var n=[],r=0;r&amp;lt;t.length;r++)if(n.push(t[r]),&amp;quot;string&amp;quot;==typeof t[r]&amp;amp;&amp;amp;0&amp;lt;t[r].indexOf(&amp;quot;-&amp;quot;)){var i=t[r].split(&amp;quot;-&amp;quot;)[0];n.push(i)}return n},n.prototype._processTranslations=function(e,t){for(var n=new s,r=0;r&amp;lt;e.length;r++){var i=new s,o=e[r];if(&amp;quot;string&amp;quot;==typeof o)try{i=s.loadPath(o)}catch(e){try{o=this.defaults.amdLanguageBase+o,i=s.loadPath(o)}catch(e){t&amp;amp;&amp;amp;window.console&amp;amp;&amp;amp;console.warn&amp;amp;&amp;amp;console.warn(&#039;Select2: The language file for &amp;quot;&#039;+o+&#039;&amp;quot; could not be automatically loaded. A fallback will be used instead.&#039;)}}else i=c.isPlainObject(o)?new s(o):o;n.extend(i)}return n},n.prototype.set=function(e,t){var n={};n[c.camelCase(e)]=t;var r=y._convertData(n);c.extend(!0,this.defaults,r)},new n}),e.define(&amp;quot;select2/options&amp;quot;,[&amp;quot;require&amp;quot;,&amp;quot;jquery&amp;quot;,&amp;quot;./defaults&amp;quot;,&amp;quot;./utils&amp;quot;],function(r,d,i,p){function e(e,t){if(this.options=e,null!=t&amp;amp;&amp;amp;this.fromElement(t),null!=t&amp;amp;&amp;amp;(this.options=i.applyFromElement(this.options,t)),this.options=i.apply(this.options),t&amp;amp;&amp;amp;t.is(&amp;quot;input&amp;quot;)){var n=r(this.get(&amp;quot;amdBase&amp;quot;)+&amp;quot;compat/inputData&amp;quot;);this.options.dataAdapter=p.Decorate(this.options.dataAdapter,n)}}return e.prototype.fromElement=function(e){var t=[&amp;quot;select2&amp;quot;];null==this.options.multiple&amp;amp;&amp;amp;(this.options.multiple=e.prop(&amp;quot;multiple&amp;quot;)),null==this.options.disabled&amp;amp;&amp;amp;(this.options.disabled=e.prop(&amp;quot;disabled&amp;quot;)),null==this.options.dir&amp;amp;&amp;amp;(e.prop(&amp;quot;dir&amp;quot;)?this.options.dir=e.prop(&amp;quot;dir&amp;quot;):e.closest(&amp;quot;[dir]&amp;quot;).prop(&amp;quot;dir&amp;quot;)?this.options.dir=e.closest(&amp;quot;[dir]&amp;quot;).prop(&amp;quot;dir&amp;quot;):this.options.dir=&amp;quot;ltr&amp;quot;),e.prop(&amp;quot;disabled&amp;quot;,this.options.disabled),e.prop(&amp;quot;multiple&amp;quot;,this.options.multiple),p.GetData(e[0],&amp;quot;select2Tags&amp;quot;)&amp;amp;&amp;amp;(this.options.debug&amp;amp;&amp;amp;window.console&amp;amp;&amp;amp;console.warn&amp;amp;&amp;amp;console.warn(&#039;Select2: The `data-select2-tags` attribute has been changed to use the `data-data` and `data-tags=&amp;quot;true&amp;quot;` attributes and will be removed in future versions of Select2.&#039;),p.StoreData(e[0],&amp;quot;data&amp;quot;,p.GetData(e[0],&amp;quot;select2Tags&amp;quot;)),p.StoreData(e[0],&amp;quot;tags&amp;quot;,!0)),p.GetData(e[0],&amp;quot;ajaxUrl&amp;quot;)&amp;amp;&amp;amp;(this.options.debug&amp;amp;&amp;amp;window.console&amp;amp;&amp;amp;console.warn&amp;amp;&amp;amp;console.warn(&amp;quot;Select2: The `data-ajax-url` attribute has been changed to `data-ajax--url` and support for the old attribute will be removed in future versions of Select2.&amp;quot;),e.attr(&amp;quot;ajax--url&amp;quot;,p.GetData(e[0],&amp;quot;ajaxUrl&amp;quot;)),p.StoreData(e[0],&amp;quot;ajax-Url&amp;quot;,p.GetData(e[0],&amp;quot;ajaxUrl&amp;quot;)));var n={};function r(e,t){return t.toUpperCase()}for(var i=0;i&amp;lt;e[0].attributes.length;i++){var o=e[0].attributes[i].name,s=&amp;quot;data-&amp;quot;;if(o.substr(0,s.length)==s){var a=o.substring(s.length),l=p.GetData(e[0],a);n[a.replace(/-([a-z])/g,r)]=l}}d.fn.jquery&amp;amp;&amp;amp;&amp;quot;1.&amp;quot;==d.fn.jquery.substr(0,2)&amp;amp;&amp;amp;e[0].dataset&amp;amp;&amp;amp;(n=d.extend(!0,{},e[0].dataset,n));var c=d.extend(!0,{},p.GetData(e[0]),n);for(var u in c=p._convertData(c))-1&amp;lt;d.inArray(u,t)||(d.isPlainObject(this.options[u])?d.extend(this.options[u],c[u]):this.options[u]=c[u]);return this},e.prototype.get=function(e){return this.options[e]},e.prototype.set=function(e,t){this.options[e]=t},e}),e.define(&amp;quot;select2/core&amp;quot;,[&amp;quot;jquery&amp;quot;,&amp;quot;./options&amp;quot;,&amp;quot;./utils&amp;quot;,&amp;quot;./keys&amp;quot;],function(i,c,u,r){var d=function(e,t){null!=u.GetData(e[0],&amp;quot;select2&amp;quot;)&amp;amp;&amp;amp;u.GetData(e[0],&amp;quot;select2&amp;quot;).destroy(),this.$element=e,this.id=this._generateId(e),t=t||{},this.options=new c(t,e),d.__super__.constructor.call(this);var n=e.attr(&amp;quot;tabindex&amp;quot;)||0;u.StoreData(e[0],&amp;quot;old-tabindex&amp;quot;,n),e.attr(&amp;quot;tabindex&amp;quot;,&amp;quot;-1&amp;quot;);var r=this.options.get(&amp;quot;dataAdapter&amp;quot;);this.dataAdapter=new r(e,this.options);var i=this.render();this._placeContainer(i);var o=this.options.get(&amp;quot;selectionAdapter&amp;quot;);this.selection=new o(e,this.options),this.$selection=this.selection.render(),this.selection.position(this.$selection,i);var s=this.options.get(&amp;quot;dropdownAdapter&amp;quot;);this.dropdown=new s(e,this.options),this.$dropdown=this.dropdown.render(),this.dropdown.position(this.$dropdown,i);var a=this.options.get(&amp;quot;resultsAdapter&amp;quot;);this.results=new a(e,this.options,this.dataAdapter),this.$results=this.results.render(),this.results.position(this.$results,this.$dropdown);var l=this;this._bindAdapters(),this._registerDomEvents(),this._registerDataEvents(),this._registerSelectionEvents(),this._registerDropdownEvents(),this._registerResultsEvents(),this._registerEvents(),this.dataAdapter.current(function(e){l.trigger(&amp;quot;selection:update&amp;quot;,{data:e})}),e.addClass(&amp;quot;select2-hidden-accessible&amp;quot;),e.attr(&amp;quot;aria-hidden&amp;quot;,&amp;quot;true&amp;quot;),this._syncAttributes(),u.StoreData(e[0],&amp;quot;select2&amp;quot;,this),e.data(&amp;quot;select2&amp;quot;,this)};return u.Extend(d,u.Observable),d.prototype._generateId=function(e){return&amp;quot;select2-&amp;quot;+(null!=e.attr(&amp;quot;id&amp;quot;)?e.attr(&amp;quot;id&amp;quot;):null!=e.attr(&amp;quot;name&amp;quot;)?e.attr(&amp;quot;name&amp;quot;)+&amp;quot;-&amp;quot;+u.generateChars(2):u.generateChars(4)).replace(/(:|\.|\[|\]|,)/g,&amp;quot;&amp;quot;)},d.prototype._placeContainer=function(e){e.insertAfter(this.$element);var t=this._resolveWidth(this.$element,this.options.get(&amp;quot;width&amp;quot;));null!=t&amp;amp;&amp;amp;e.css(&amp;quot;width&amp;quot;,t)},d.prototype._resolveWidth=function(e,t){var n=/^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;if(&amp;quot;resolve&amp;quot;==t){var r=this._resolveWidth(e,&amp;quot;style&amp;quot;);return null!=r?r:this._resolveWidth(e,&amp;quot;element&amp;quot;)}if(&amp;quot;element&amp;quot;==t){var i=e.outerWidth(!1);return i&amp;lt;=0?&amp;quot;auto&amp;quot;:i+&amp;quot;px&amp;quot;}if(&amp;quot;style&amp;quot;!=t)return&amp;quot;computedstyle&amp;quot;!=t?t:window.getComputedStyle(e[0]).width;var o=e.attr(&amp;quot;style&amp;quot;);if(&amp;quot;string&amp;quot;!=typeof o)return null;for(var s=o.split(&amp;quot;;&amp;quot;),a=0,l=s.length;a&amp;lt;l;a+=1){var c=s[a].replace(/\s/g,&amp;quot;&amp;quot;).match(n);if(null!==c&amp;amp;&amp;amp;1&amp;lt;=c.length)return c[1]}return null},d.prototype._bindAdapters=function(){this.dataAdapter.bind(this,this.$container),this.selection.bind(this,this.$container),this.dropdown.bind(this,this.$container),this.results.bind(this,this.$container)},d.prototype._registerDomEvents=function(){var t=this;this.$element.on(&amp;quot;change.select2&amp;quot;,function(){t.dataAdapter.current(function(e){t.trigger(&amp;quot;selection:update&amp;quot;,{data:e})})}),this.$element.on(&amp;quot;focus.select2&amp;quot;,function(e){t.trigger(&amp;quot;focus&amp;quot;,e)}),this._syncA=u.bind(this._syncAttributes,this),this._syncS=u.bind(this._syncSubtree,this),this.$element[0].attachEvent&amp;amp;&amp;amp;this.$element[0].attachEvent(&amp;quot;onpropertychange&amp;quot;,this._syncA);var e=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver;null!=e?(this._observer=new e(function(e){i.each(e,t._syncA),i.each(e,t._syncS)}),this._observer.observe(this.$element[0],{attributes:!0,childList:!0,subtree:!1})):this.$element[0].addEventListener&amp;amp;&amp;amp;(this.$element[0].addEventListener(&amp;quot;DOMAttrModified&amp;quot;,t._syncA,!1),this.$element[0].addEventListener(&amp;quot;DOMNodeInserted&amp;quot;,t._syncS,!1),this.$element[0].addEventListener(&amp;quot;DOMNodeRemoved&amp;quot;,t._syncS,!1))},d.prototype._registerDataEvents=function(){var n=this;this.dataAdapter.on(&amp;quot;*&amp;quot;,function(e,t){n.trigger(e,t)})},d.prototype._registerSelectionEvents=function(){var n=this,r=[&amp;quot;toggle&amp;quot;,&amp;quot;focus&amp;quot;];this.selection.on(&amp;quot;toggle&amp;quot;,function(){n.toggleDropdown()}),this.selection.on(&amp;quot;focus&amp;quot;,function(e){n.focus(e)}),this.selection.on(&amp;quot;*&amp;quot;,function(e,t){-1===i.inArray(e,r)&amp;amp;&amp;amp;n.trigger(e,t)})},d.prototype._registerDropdownEvents=function(){var n=this;this.dropdown.on(&amp;quot;*&amp;quot;,function(e,t){n.trigger(e,t)})},d.prototype._registerResultsEvents=function(){var n=this;this.results.on(&amp;quot;*&amp;quot;,function(e,t){n.trigger(e,t)})},d.prototype._registerEvents=function(){var n=this;this.on(&amp;quot;open&amp;quot;,function(){n.$container.addClass(&amp;quot;select2-container--open&amp;quot;)}),this.on(&amp;quot;close&amp;quot;,function(){n.$container.removeClass(&amp;quot;select2-container--open&amp;quot;)}),this.on(&amp;quot;enable&amp;quot;,function(){n.$container.removeClass(&amp;quot;select2-container--disabled&amp;quot;)}),this.on(&amp;quot;disable&amp;quot;,function(){n.$container.addClass(&amp;quot;select2-container--disabled&amp;quot;)}),this.on(&amp;quot;blur&amp;quot;,function(){n.$container.removeClass(&amp;quot;select2-container--focus&amp;quot;)}),this.on(&amp;quot;query&amp;quot;,function(t){n.isOpen()||n.trigger(&amp;quot;open&amp;quot;,{}),this.dataAdapter.query(t,function(e){n.trigger(&amp;quot;results:all&amp;quot;,{data:e,query:t})})}),this.on(&amp;quot;query:append&amp;quot;,function(t){this.dataAdapter.query(t,function(e){n.trigger(&amp;quot;results:append&amp;quot;,{data:e,query:t})})}),this.on(&amp;quot;keypress&amp;quot;,function(e){var t=e.which;n.isOpen()?t===r.ESC||t===r.TAB||t===r.UP&amp;amp;&amp;amp;e.altKey?(n.close(),e.preventDefault()):t===r.ENTER?(n.trigger(&amp;quot;results:select&amp;quot;,{}),e.preventDefault()):t===r.SPACE&amp;amp;&amp;amp;e.ctrlKey?(n.trigger(&amp;quot;results:toggle&amp;quot;,{}),e.preventDefault()):t===r.UP?(n.trigger(&amp;quot;results:previous&amp;quot;,{}),e.preventDefault()):t===r.DOWN&amp;amp;&amp;amp;(n.trigger(&amp;quot;results:next&amp;quot;,{}),e.preventDefault()):(t===r.ENTER||t===r.SPACE||t===r.DOWN&amp;amp;&amp;amp;e.altKey)&amp;amp;&amp;amp;(n.open(),e.preventDefault())})},d.prototype._syncAttributes=function(){this.options.set(&amp;quot;disabled&amp;quot;,this.$element.prop(&amp;quot;disabled&amp;quot;)),this.options.get(&amp;quot;disabled&amp;quot;)?(this.isOpen()&amp;amp;&amp;amp;this.close(),this.trigger(&amp;quot;disable&amp;quot;,{})):this.trigger(&amp;quot;enable&amp;quot;,{})},d.prototype._syncSubtree=function(e,t){var n=!1,r=this;if(!e||!e.target||&amp;quot;OPTION&amp;quot;===e.target.nodeName||&amp;quot;OPTGROUP&amp;quot;===e.target.nodeName){if(t)if(t.addedNodes&amp;amp;&amp;amp;0&amp;lt;t.addedNodes.length)for(var i=0;i&amp;lt;t.addedNodes.length;i++){t.addedNodes[i].selected&amp;amp;&amp;amp;(n=!0)}else t.removedNodes&amp;amp;&amp;amp;0&amp;lt;t.removedNodes.length&amp;amp;&amp;amp;(n=!0);else n=!0;n&amp;amp;&amp;amp;this.dataAdapter.current(function(e){r.trigger(&amp;quot;selection:update&amp;quot;,{data:e})})}},d.prototype.trigger=function(e,t){var n=d.__super__.trigger,r={open:&amp;quot;opening&amp;quot;,close:&amp;quot;closing&amp;quot;,select:&amp;quot;selecting&amp;quot;,unselect:&amp;quot;unselecting&amp;quot;,clear:&amp;quot;clearing&amp;quot;};if(void 0===t&amp;amp;&amp;amp;(t={}),e in r){var i=r[e],o={prevented:!1,name:e,args:t};if(n.call(this,i,o),o.prevented)return void(t.prevented=!0)}n.call(this,e,t)},d.prototype.toggleDropdown=function(){this.options.get(&amp;quot;disabled&amp;quot;)||(this.isOpen()?this.close():this.open())},d.prototype.open=function(){this.isOpen()||this.trigger(&amp;quot;query&amp;quot;,{})},d.prototype.close=function(){this.isOpen()&amp;amp;&amp;amp;this.trigger(&amp;quot;close&amp;quot;,{})},d.prototype.isOpen=function(){return this.$container.hasClass(&amp;quot;select2-container--open&amp;quot;)},d.prototype.hasFocus=function(){return this.$container.hasClass(&amp;quot;select2-container--focus&amp;quot;)},d.prototype.focus=function(e){this.hasFocus()||(this.$container.addClass(&amp;quot;select2-container--focus&amp;quot;),this.trigger(&amp;quot;focus&amp;quot;,{}))},d.prototype.enable=function(e){this.options.get(&amp;quot;debug&amp;quot;)&amp;amp;&amp;amp;window.console&amp;amp;&amp;amp;console.warn&amp;amp;&amp;amp;console.warn(&#039;Select2: The `select2(&amp;quot;enable&amp;quot;)` method has been deprecated and will be removed in later Select2 versions. Use $element.prop(&amp;quot;disabled&amp;quot;) instead.&#039;),null!=e&amp;amp;&amp;amp;0!==e.length||(e=[!0]);var t=!e[0];this.$element.prop(&amp;quot;disabled&amp;quot;,t)},d.prototype.data=function(){this.options.get(&amp;quot;debug&amp;quot;)&amp;amp;&amp;amp;0&amp;lt;arguments.length&amp;amp;&amp;amp;window.console&amp;amp;&amp;amp;console.warn&amp;amp;&amp;amp;console.warn(&#039;Select2: Data can no longer be set using `select2(&amp;quot;data&amp;quot;)`. You should consider setting the value instead using `$element.val()`.&#039;);var t=[];return this.dataAdapter.current(function(e){t=e}),t},d.prototype.val=function(e){if(this.options.get(&amp;quot;debug&amp;quot;)&amp;amp;&amp;amp;window.console&amp;amp;&amp;amp;console.warn&amp;amp;&amp;amp;console.warn(&#039;Select2: The `select2(&amp;quot;val&amp;quot;)` method has been deprecated and will be removed in later Select2 versions. Use $element.val() instead.&#039;),null==e||0===e.length)return this.$element.val();var t=e[0];i.isArray(t)&amp;amp;&amp;amp;(t=i.map(t,function(e){return e.toString()})),this.$element.val(t).trigger(&amp;quot;change&amp;quot;)},d.prototype.destroy=function(){this.$container.remove(),this.$element[0].detachEvent&amp;amp;&amp;amp;this.$element[0].detachEvent(&amp;quot;onpropertychange&amp;quot;,this._syncA),null!=this._observer?(this._observer.disconnect(),this._observer=null):this.$element[0].removeEventListener&amp;amp;&amp;amp;(this.$element[0].removeEventListener(&amp;quot;DOMAttrModified&amp;quot;,this._syncA,!1),this.$element[0].removeEventListener(&amp;quot;DOMNodeInserted&amp;quot;,this._syncS,!1),this.$element[0].removeEventListener(&amp;quot;DOMNodeRemoved&amp;quot;,this._syncS,!1)),this._syncA=null,this._syncS=null,this.$element.off(&amp;quot;.select2&amp;quot;),this.$element.attr(&amp;quot;tabindex&amp;quot;,u.GetData(this.$element[0],&amp;quot;old-tabindex&amp;quot;)),this.$element.removeClass(&amp;quot;select2-hidden-accessible&amp;quot;),this.$element.attr(&amp;quot;aria-hidden&amp;quot;,&amp;quot;false&amp;quot;),u.RemoveData(this.$element[0]),this.$element.removeData(&amp;quot;select2&amp;quot;),this.dataAdapter.destroy(),this.selection.destroy(),this.dropdown.destroy(),this.results.destroy(),this.dataAdapter=null,this.selection=null,this.dropdown=null,this.results=null},d.prototype.render=function(){var e=i(&#039;&amp;lt;span class=&amp;quot;select2 select2-container&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;selection&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;dropdown-wrapper&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039;);return e.attr(&amp;quot;dir&amp;quot;,this.options.get(&amp;quot;dir&amp;quot;)),this.$container=e,this.$container.addClass(&amp;quot;select2-container--&amp;quot;+this.options.get(&amp;quot;theme&amp;quot;)),u.StoreData(e[0],&amp;quot;element&amp;quot;,this.$element),e},d}),e.define(&amp;quot;jquery-mousewheel&amp;quot;,[&amp;quot;jquery&amp;quot;],function(e){return e}),e.define(&amp;quot;jquery.select2&amp;quot;,[&amp;quot;jquery&amp;quot;,&amp;quot;jquery-mousewheel&amp;quot;,&amp;quot;./select2/core&amp;quot;,&amp;quot;./select2/defaults&amp;quot;,&amp;quot;./select2/utils&amp;quot;],function(i,e,o,t,s){if(null==i.fn.select2){var a=[&amp;quot;open&amp;quot;,&amp;quot;close&amp;quot;,&amp;quot;destroy&amp;quot;];i.fn.select2=function(t){if(&amp;quot;object&amp;quot;==typeof(t=t||{}))return this.each(function(){var e=i.extend(!0,{},t);new o(i(this),e)}),this;if(&amp;quot;string&amp;quot;!=typeof t)throw new Error(&amp;quot;Invalid arguments for Select2: &amp;quot;+t);var n,r=Array.prototype.slice.call(arguments,1);return this.each(function(){var e=s.GetData(this,&amp;quot;select2&amp;quot;);null==e&amp;amp;&amp;amp;window.console&amp;amp;&amp;amp;console.error&amp;amp;&amp;amp;console.error(&amp;quot;The select2(&#039;&amp;quot;+t+&amp;quot;&#039;) method was called on an element that is not using Select2.&amp;quot;),n=e[t].apply(e,r)}),-1&amp;lt;i.inArray(t,a)?this:n}}return null==i.fn.select2.defaults&amp;amp;&amp;amp;(i.fn.select2.defaults=t),o}),{define:e.define,require:e.require}}(),t=e.require(&amp;quot;jquery.select2&amp;quot;);return u.fn.select2.amd=e,t});&lt;br /&gt;
&lt;br /&gt;
// &amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-WikiMiniAtlas&amp;diff=120485</id>
		<title>MediaWiki:Gadget-WikiMiniAtlas</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-WikiMiniAtlas&amp;diff=120485"/>
		<updated>2026-06-24T20:24:18Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: ←Created page with &amp;#039;&amp;lt;sup&amp;gt;&amp;lt;abbr title=&amp;quot;{{int:gadgets-default}}&amp;quot;&amp;gt;(D)&amp;lt;/abbr&amp;gt;&amp;lt;/sup&amp;gt; WikiMiniAtlas: Popup maps on articles with coordinates&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;sup&amp;gt;&amp;lt;abbr title=&amp;quot;{{int:gadgets-default}}&amp;quot;&amp;gt;(D)&amp;lt;/abbr&amp;gt;&amp;lt;/sup&amp;gt; [[m:WikiMiniAtlas|WikiMiniAtlas]]: Popup maps on articles with coordinates&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-WikiMiniAtlas.js&amp;diff=120484</id>
		<title>MediaWiki:Gadget-WikiMiniAtlas.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-WikiMiniAtlas.js&amp;diff=120484"/>
		<updated>2026-06-24T20:23:35Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: ←Created page with &amp;#039; /******************************************************************************/ /**** THIS PAGE TRACKS meta:MediaWiki:Wikiminiatlas.js. PLEASE AVOID EDITING DIRECTLY.  /**** EDITS SHOULD BE PROPOSED DIRECTLY to meta:MediaWiki:Wikiminiatlas.js. /**** A BOT WILL RAISE AN EDIT REQUEST IF IT BECOMES DIFFERENT FROM UPSTREAM. /******************************************************************************/  // &amp;#039;&amp;#039;&amp;#039;WikiMiniAtlas&amp;#039;&amp;#039;&amp;#039; // Script to embed inter...&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
/**** THIS PAGE TRACKS [[meta:MediaWiki:Wikiminiatlas.js]]. PLEASE AVOID EDITING DIRECTLY. &lt;br /&gt;
/**** EDITS SHOULD BE PROPOSED DIRECTLY to [[meta:MediaWiki:Wikiminiatlas.js]].&lt;br /&gt;
/**** A BOT WILL RAISE AN EDIT REQUEST IF IT BECOMES DIFFERENT FROM UPSTREAM.&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
// &#039;&#039;&#039;WikiMiniAtlas&#039;&#039;&#039;&lt;br /&gt;
// Script to embed interactive maps into pages that have coordinate templates&lt;br /&gt;
// also check my user page [[User:Dschwen]] for more tools&lt;br /&gt;
//&lt;br /&gt;
// Revision 16.12&lt;br /&gt;
// Source: https://github.com/dschwen/wikiminiatlas/blob/master/wikiminiatlas.js&lt;br /&gt;
// License: CC BY-SA 4.0 and GFDL&lt;br /&gt;
/* jshint laxcomma:true, smarttabs:true, quotmark:single, curly:false, es3:true, browser:true */&lt;br /&gt;
/* global mw,jQuery */&lt;br /&gt;
jQuery(function ($) {&lt;br /&gt;
 // WMA config&lt;br /&gt;
 var wc = {&lt;br /&gt;
  width  : 600,&lt;br /&gt;
  height : 400,&lt;br /&gt;
  timeout : 5000,&lt;br /&gt;
  zoom : -1,&lt;br /&gt;
  enabled : true,&lt;br /&gt;
  onlytitle : false,&lt;br /&gt;
  flowTextTooltips: (location.host===&#039;en.wikipedia.org&#039;),&lt;br /&gt;
  alwaysTooltips: false,&lt;br /&gt;
  iframeurl : &#039;//wma.wmcloud.org/iframe.html&#039;,&lt;br /&gt;
  imgbase   : &#039;//wma.wmcloud.org/tiles/&#039;,&lt;br /&gt;
  buttonImage: &#039;//upload.wikimedia.org/wikipedia/commons/thumb/5/55/WMA_button2b.png/20px-WMA_button2b.png&#039;,&lt;br /&gt;
  buttonImage2x: &#039;//upload.wikimedia.org/wikipedia/commons/thumb/5/55/WMA_button2b.png/40px-WMA_button2b.png&#039;,&lt;br /&gt;
  buttonWidth: 17,&lt;br /&gt;
  buttonHeight: 17&lt;br /&gt;
 },&lt;br /&gt;
 strings = {&lt;br /&gt;
  buttonTooltip : {&lt;br /&gt;
   &#039;af&#039;:&#039;Vertoon ligging op \&#039;n interaktiwe kaart.&#039;,&lt;br /&gt;
   &#039;als&#039;:&#039;Ort uf dr interaktivä Chartä zeigä&#039;,&lt;br /&gt;
   &#039;ar&#039;:&#039;شاهد الموقع على الخريطة التفاعلية&#039;,&lt;br /&gt;
   &#039;ast&#039;:&#039;Ver el llugar nun mapa interactivu&#039;,&lt;br /&gt;
   &#039;az&#039;:&#039;Yeri interaktiv bir xəritədə göstər&#039;,&lt;br /&gt;
   &#039;bar&#039;:&#039;Ort af da interaktivn Kartn zoagn&#039;,&lt;br /&gt;
   &#039;be-tarask&#039;:&#039;паказаць месцазнаходжаньне на інтэрактыўнай мапе&#039;,&lt;br /&gt;
   &#039;be-x-old&#039;:&#039;паказаць месцазнаходжаньне на інтэрактыўнай мапе&#039;,&lt;br /&gt;
   &#039;bg&#039;:&#039;Покажи местоположението на интерактивната карта&#039;,&lt;br /&gt;
   &#039;bn&#039;:&#039;সক্রিয় মানচিত্রে অবস্থান চিহ্নিত করুন&#039;,&lt;br /&gt;
   &#039;bpy&#039;:&#039;জীবন্ত মানচিত্রগর মা মাপাহান দেখাদিতই&#039;,&lt;br /&gt;
   &#039;br&#039;:&#039;diskouez al lec\&#039;hiadur war ur gartenn etrewezhiat&#039;,&lt;br /&gt;
   &#039;bs&#039;:&#039;Prikaži lokaciju na interaktivnoj mapi&#039;,&lt;br /&gt;
   &#039;ca&#039;:&#039;Mostra la localització en un mapa interactiu&#039;,&lt;br /&gt;
   &#039;cs&#039;:&#039;zobrazit místo na interaktivní mapě&#039;,&lt;br /&gt;
   &#039;da&#039;:&#039;vis beliggenhed på interaktivt kort&#039;,&lt;br /&gt;
   &#039;de&#039;:&#039;Ort auf interaktiver Karte anzeigen&#039;,&lt;br /&gt;
   &#039;dsb&#039;:&#039;Městno na interaktiwnej kórśe zwobrazniś&#039;,&lt;br /&gt;
   &#039;el&#039;:&#039;Εμφάνιση τοποθεσίας σε διαδραστικό χάρτη&#039;,&lt;br /&gt;
   &#039;en&#039;:&#039;Show location on an interactive map&#039;,&lt;br /&gt;
   &#039;eo&#039;:&#039;Montru lokigon sur interaktiva karto&#039;,&lt;br /&gt;
   &#039;es&#039;:&#039;Mostrar el lugar en un mapa interactivo&#039;,&lt;br /&gt;
   &#039;eu&#039;:&#039;erakutsi kokalekua mapa interaktibo batean&#039;,&lt;br /&gt;
   &#039;fa&#039;:&#039;نمایش مکان در نقشه‌ای پویا&#039;,&lt;br /&gt;
   &#039;fi&#039;:&#039;näytä paikka interaktiivisella kartalla&#039;,&lt;br /&gt;
   &#039;fr&#039;:&#039;Montrer la localisation sur une carte interactive&#039;,&lt;br /&gt;
   &#039;fur&#039;:&#039;mostre la localizazion suntune mape interative&#039;,&lt;br /&gt;
   &#039;fy&#039;:&#039;it plak op in oanpasbere kaart oanjaan&#039;,&lt;br /&gt;
   &#039;gl&#039;:&#039;Amosar o lugar nun mapa interactivo&#039;,&lt;br /&gt;
   &#039;he&#039;:&#039;הראה מיקום במפה האינטראקטיבית&#039;,&lt;br /&gt;
   &#039;hi&#039;:&#039;सक्रिय नक्शे पर लोकेशन या स्थान दिखायें&#039;,&lt;br /&gt;
   &#039;hr&#039;:&#039;Prikaži lokaciju na interaktivnom zemljovidu&#039;,&lt;br /&gt;
   &#039;hsb&#039;:&#039;Městno na interaktiwnej karće zwobraznić&#039;,&lt;br /&gt;
   &#039;hu&#039;:&#039;Mutasd a helyet egy interaktív térképen!&#039;,&lt;br /&gt;
   &#039;hy&#039;:&#039;ցուցադրել դիրքը ինտերակտիվ քարտեզի վրա&#039;,&lt;br /&gt;
   &#039;id&#039;:&#039;Tunjukkan lokasi di peta interaktif&#039;,&lt;br /&gt;
   &#039;ilo&#039;:&#039;Ipakita ti lokasion iti interaktibo a mapa&#039;,&lt;br /&gt;
   &#039;is&#039;:&#039;sýna staðsetningu á gagnvirku korti&#039;,&lt;br /&gt;
   &#039;it&#039;:&#039;mostra la località su una carta interattiva&#039;,&lt;br /&gt;
   &#039;ja&#039;:&#039;インタラクティブ地図上に位置を表示&#039;,&lt;br /&gt;
   &#039;kk&#039;:&#039;интерактивті картадан орналасуын көрсету&#039;,&lt;br /&gt;
   &#039;km&#039;:&#039;បង្ហាញទីតាំងនៅលើផែនទីអន្តរកម្ម&#039;,&lt;br /&gt;
   &#039;kn&#039;:&#039;ನಕ್ಷೆಯಲ್ಲಿ ಸ್ಥಳವನ್ನು ತೋರಿಸು&#039;,&lt;br /&gt;
   &#039;ko&#039;:&#039;인터랙티브 지도에 위치를 표시&#039;,&lt;br /&gt;
   &#039;ku&#039;:&#039;Vî cihê li ser nexşeyekî înteraktifê nişan bide&#039;,&lt;br /&gt;
   &#039;lt&#039;:&#039;Rodyti vietą interaktyviame žemėlapyje&#039;,&lt;br /&gt;
   &#039;lv&#039;:&#039;Rādīt atrašanās vietu interaktīvajā kartē&#039;,&lt;br /&gt;
   &#039;min&#039;:&#039;Tunjuakan lokasi pado peta&#039;,&lt;br /&gt;
   &#039;mk&#039;:&#039;прикажи положба на интерактивна карта&#039;,&lt;br /&gt;
   &#039;ml&#039;:&#039;സ്ഥാനം സംവേദനക്ഷമമായ ഒരു ഭൂപടത്തിൽ കാണിക്കുക&#039;,&lt;br /&gt;
   &#039;ms&#039;:&#039;Tunjukkan lokasi pada peta interaktif&#039;,&lt;br /&gt;
   &#039;my&#039;:&#039;မြေပုံပေါ်တွင် တည်နေရာပြရန်&#039;,&lt;br /&gt;
   &#039;nl&#039;:&#039;de locatie op een interactieve kaart tonen&#039;,&lt;br /&gt;
   &#039;no&#039;:&#039;vis beliggenhet på interaktivt kart&#039;,&lt;br /&gt;
   &#039;nv&#039;:&#039;kéyah tʼáá dah siʼą́ą́ ńtʼę́ę́ʼ beʼelyaaígíí&#039;,&lt;br /&gt;
   &#039;pl&#039;:&#039;Pokaż lokalizację na mapie interaktywnej&#039;,&lt;br /&gt;
   &#039;ps&#039;:&#039;د ځاي نخشه ښکاره کول په متقابله نخشه کې&#039;,&lt;br /&gt;
   &#039;pt&#039;:&#039;mostrar a localidade num mapa interactivo&#039;,&lt;br /&gt;
   &#039;ro&#039;:&#039;Arată locaţia pe o hartă interactivă&#039;,&lt;br /&gt;
   &#039;ru&#039;:&#039;показать положение на интерактивной карте&#039;,&lt;br /&gt;
   &#039;sco&#039;:&#039;Shaw location on an interactive cairt&#039;,&lt;br /&gt;
   &#039;sh&#039;:&#039;Prikaži lokaciju na interaktivnoj mapi&#039;,&lt;br /&gt;
   &#039;sk&#039;:&#039;zobraz miesto na interaktívnej mape&#039;,&lt;br /&gt;
   &#039;sl&#039;:&#039;Prikaži lego na interaktivnem zemljevidu&#039;,&lt;br /&gt;
   &#039;sq&#039;:&#039;trego vendndodhjen në hartë&#039;,&lt;br /&gt;
   &#039;sr&#039;:&#039;Прикажи локацију на интерактивној мапи&#039;,&lt;br /&gt;
   &#039;sr-ec&#039;:&#039;Прикажи локацију на интерактивној мапи&#039;,&lt;br /&gt;
   &#039;sr-el&#039;:&#039;Prikaži lokaciju na interaktivnoj mapi&#039;,&lt;br /&gt;
   &#039;sv&#039;:&#039;visa platsen på en interaktiv karta&#039;,&lt;br /&gt;
   &#039;th&#039;:&#039;แสดงตำแหน่งบนแผนที่เชิงโต้ตอบ&#039;,&lt;br /&gt;
   &#039;ti&#039;: &#039;ቦታ ኣብ ተገባባሪ ካርታ ኣርእይ&#039;,&lt;br /&gt;
   &#039;tr&#039;:&#039;Yeri interaktif bir haritada göster&#039;,&lt;br /&gt;
   &#039;uk&#039;:&#039;показати положення на інтерактивній мапі&#039;,&lt;br /&gt;
   &#039;vi&#039;:&#039;xem vị trí này trên bản đồ tương tác&#039;,&lt;br /&gt;
   &#039;vo&#039;:&#039;Jonön topi su kaed itjäfidik&#039;,&lt;br /&gt;
   &#039;zh&#039;:&#039;显示该地在地图上的位置&#039;,&lt;br /&gt;
   &#039;zh-cn&#039;:&#039;显示该地在地图上的位置&#039;,&lt;br /&gt;
   &#039;zh-hk&#039;:&#039;顯示該地在地圖上的位置&#039;,&lt;br /&gt;
   &#039;zh-sg&#039;:&#039;显示该地在地图上的位置&#039;,&lt;br /&gt;
   &#039;zh-tw&#039;:&#039;顯示該地在地圖上的位置&#039;,&lt;br /&gt;
   &#039;zh-yue&#039;:&#039;顯示當地喺地圖度嘅位置&#039;&lt;br /&gt;
  },&lt;br /&gt;
  &#039;map&#039;: {&lt;br /&gt;
   &#039;ast&#039;:&#039;Mapa&#039;,&lt;br /&gt;
   &#039;az&#039;:&#039;Xəritə&#039;,&lt;br /&gt;
   &#039;bg&#039;:&#039;Карта&#039;,&lt;br /&gt;
   &#039;bn&#039;:&#039;মানচিত্র&#039;,&lt;br /&gt;
   &#039;bs&#039;:&#039;Mapa&#039;,&lt;br /&gt;
   &#039;ca&#039;:&#039;Mapa&#039;,&lt;br /&gt;
   &#039;cs&#039;:&#039;Mapa&#039;,&lt;br /&gt;
   &#039;de&#039;:&#039;Karte&#039;,&lt;br /&gt;
   &#039;el&#039;:&#039;Χάρτης&#039;,&lt;br /&gt;
   &#039;en&#039;:&#039;Map&#039;,&lt;br /&gt;
   &#039;es&#039;:&#039;Mapa&#039;,&lt;br /&gt;
   &#039;fa&#039;:&#039;نقشه&#039;,&lt;br /&gt;
   &#039;fi&#039;:&#039;Kartalla&#039;,&lt;br /&gt;
   &#039;fr&#039;:&#039;Carte&#039;,&lt;br /&gt;
   &#039;gl&#039;:&#039;Mapa&#039;,&lt;br /&gt;
   &#039;hr&#039;:&#039;Zemljovid&#039;,&lt;br /&gt;
   &#039;hu&#039;:&#039;Térkép&#039;,&lt;br /&gt;
   &#039;id&#039;:&#039;peta&#039;,&lt;br /&gt;
   &#039;ilo&#039;:&#039;Mapa&#039;,&lt;br /&gt;
   &#039;it&#039;:&#039;Mappa&#039;,&lt;br /&gt;
   &#039;ja&#039;:&#039;地図&#039;,&lt;br /&gt;
   &#039;kn&#039;:&#039;ನಕ್ಷೆ&#039;,&lt;br /&gt;
   &#039;ku&#039;:&#039;Nexşe&#039;,&lt;br /&gt;
   &#039;min&#039;:&#039;peta&#039;,&lt;br /&gt;
   &#039;mk&#039;:&#039;Карта&#039;,&lt;br /&gt;
   &#039;ml&#039;:&#039;ഭൂപടം&#039;,&lt;br /&gt;
   &#039;ms&#039;:&#039;Peta&#039;,&lt;br /&gt;
   &#039;my&#039;:&#039;မြေပုံညွှန်း&#039;,&lt;br /&gt;
   &#039;nl&#039;:&#039;Kaart&#039;,&lt;br /&gt;
   &#039;ps&#039;:&#039;نخشه&#039;,&lt;br /&gt;
   &#039;pt&#039;:&#039;Mapa&#039;,&lt;br /&gt;
   &#039;ru&#039;:&#039;карте&#039;,&lt;br /&gt;
   &#039;sco&#039;:&#039;Cairt&#039;,&lt;br /&gt;
   &#039;sh&#039;:&#039;Mapa&#039;,&lt;br /&gt;
   &#039;sr&#039;:&#039;Мапа&#039;,&lt;br /&gt;
   &#039;sr-ec&#039;:&#039;Мапа&#039;,&lt;br /&gt;
   &#039;sr-el&#039;:&#039;Mapa&#039;,&lt;br /&gt;
   &#039;sv&#039;:&#039;Karta&#039;,&lt;br /&gt;
   &#039;th&#039;:&#039;แผนที่&#039;,&lt;br /&gt;
   &#039;ti&#039;:&#039;ካርታ&#039;,&lt;br /&gt;
   &#039;uk&#039;:&#039;мапі&#039;,&lt;br /&gt;
   &#039;zh&#039;:&#039;地圖&#039;,&lt;br /&gt;
   &#039;zh-cn&#039;:&#039;地图&#039;,&lt;br /&gt;
   &#039;zh-hk&#039;:&#039;地圖&#039;,&lt;br /&gt;
   &#039;zh-sg&#039;:&#039;地图&#039;,&lt;br /&gt;
   &#039;zh-tw&#039;:&#039;地圖&#039;,&lt;br /&gt;
   &#039;zh-yue&#039;:&#039;地圖&#039;&lt;br /&gt;
  },&lt;br /&gt;
  close : {&lt;br /&gt;
   &#039;af&#039;:&#039;Sluit&#039;,&lt;br /&gt;
   &#039;als&#039;:&#039;Zuä machä&#039;,&lt;br /&gt;
   &#039;ar&#039;:&#039;غلق&#039;,&lt;br /&gt;
   &#039;ast&#039;:&#039;zarrar&#039;,&lt;br /&gt;
   &#039;az&#039;:&#039;bağla&#039;,&lt;br /&gt;
   &#039;be-tarask&#039;:&#039;закрыць&#039;,&lt;br /&gt;
   &#039;be-x-old&#039;:&#039;закрыць&#039;,&lt;br /&gt;
   &#039;bar&#039;:&#039;zuamachn&#039;,&lt;br /&gt;
   &#039;bg&#039;:&#039;Затвори&#039;,&lt;br /&gt;
   &#039;bn&#039;:&#039;বন্ধ করুন&#039;,&lt;br /&gt;
   &#039;bpy&#039;:&#039;জিপা&#039;,&lt;br /&gt;
   &#039;br&#039;:&#039;serriñ&#039;,&lt;br /&gt;
   &#039;bs&#039;:&#039;zatvori&#039;,&lt;br /&gt;
   &#039;ca&#039;:&#039;Tanca&#039;,&lt;br /&gt;
   &#039;cs&#039;:&#039;zavřít&#039;,&lt;br /&gt;
   &#039;da&#039;:&#039;luk&#039;,&lt;br /&gt;
   &#039;de&#039;:&#039;schließen&#039;,&lt;br /&gt;
   &#039;dsb&#039;:&#039;zacyniś&#039;,&lt;br /&gt;
   &#039;el&#039;:&#039;έξοδος&#039;,&lt;br /&gt;
   &#039;en&#039;:&#039;close&#039;,&lt;br /&gt;
   &#039;eo&#039;:&#039;fermu&#039;,&lt;br /&gt;
   &#039;es&#039;:&#039;cerrar&#039;,&lt;br /&gt;
   &#039;eu&#039;:&#039;itxi&#039;,&lt;br /&gt;
   &#039;fa&#039;:&#039;بستن&#039;,&lt;br /&gt;
   &#039;fi&#039;:&#039;sulje&#039;,&lt;br /&gt;
   &#039;fr&#039;:&#039;Quitter&#039;,&lt;br /&gt;
   &#039;fur&#039;:&#039;siere&#039;,&lt;br /&gt;
   &#039;fy&#039;:&#039;ticht&#039;,&lt;br /&gt;
   &#039;gl&#039;:&#039;pechar&#039;,&lt;br /&gt;
   &#039;he&#039;:&#039;לסגור&#039;,&lt;br /&gt;
   &#039;hi&#039;:&#039;बंद करें&#039;,&lt;br /&gt;
   &#039;hr&#039;:&#039;zatvori&#039;,&lt;br /&gt;
   &#039;hsb&#039;:&#039;začinić&#039;,&lt;br /&gt;
   &#039;hu&#039;:&#039;bezárás&#039;,&lt;br /&gt;
   &#039;hy&#039;:&#039;փակել&#039;,&lt;br /&gt;
   &#039;id&#039;:&#039;tutup&#039;,&lt;br /&gt;
   &#039;ilo&#039;:&#039;irikep&#039;,&lt;br /&gt;
   &#039;is&#039;:&#039;loka&#039;,&lt;br /&gt;
   &#039;it&#039;:&#039;chiudi&#039;,&lt;br /&gt;
   &#039;ja&#039;:&#039;閉じる&#039;,&lt;br /&gt;
   &#039;kk&#039;:&#039;жабу&#039;,&lt;br /&gt;
   &#039;km&#039;:&#039;បិទ&#039;,&lt;br /&gt;
   &#039;kn&#039;:&#039;ಮುಚ್ಚಿರಿ&#039;,&lt;br /&gt;
   &#039;ko&#039;:&#039;닫기&#039;,&lt;br /&gt;
   &#039;ku&#039;:&#039;daxe&#039;,&lt;br /&gt;
   &#039;lt&#039;:&#039;uždaryti&#039;,&lt;br /&gt;
   &#039;lv&#039;:&#039;aizvērt&#039;,&lt;br /&gt;
   &#039;min&#039;:&#039;tutuik&#039;,&lt;br /&gt;
   &#039;mk&#039;:&#039;затвори&#039;,&lt;br /&gt;
   &#039;ml&#039;:&#039;അടയ്ക്കുക&#039;,&lt;br /&gt;
   &#039;ms&#039;:&#039;tutup&#039;,&lt;br /&gt;
   &#039;my&#039;:&#039;ပိတ်ရန်&#039;,&lt;br /&gt;
   &#039;nl&#039;:&#039;sluiten&#039;,&lt;br /&gt;
   &#039;no&#039;:&#039;lukk&#039;,&lt;br /&gt;
   &#039;ps&#039;:&#039;تړل&#039;,&lt;br /&gt;
   &#039;nv&#039;:&#039;doo yishʼį́ nisin da&#039;,&lt;br /&gt;
   &#039;pl&#039;:&#039;zamknij&#039;,&lt;br /&gt;
   &#039;pt&#039;:&#039;fechar&#039;,&lt;br /&gt;
   &#039;ro&#039;:&#039;închide&#039;,&lt;br /&gt;
   &#039;ru&#039;:&#039;закрыть&#039;,&lt;br /&gt;
   &#039;sh&#039;:&#039;zatvori&#039;,&lt;br /&gt;
   &#039;sk&#039;:&#039;zatvoriť&#039;,&lt;br /&gt;
   &#039;sl&#039;:&#039;zapri&#039;,&lt;br /&gt;
   &#039;sq&#039;:&#039;mbylle&#039;,&lt;br /&gt;
   &#039;sr&#039;:&#039;затвори&#039;,&lt;br /&gt;
   &#039;sr-ec&#039;:&#039;затвори&#039;,&lt;br /&gt;
   &#039;sr-el&#039;:&#039;zatvori&#039;,&lt;br /&gt;
   &#039;sv&#039;:&#039;stäng&#039;,&lt;br /&gt;
   &#039;th&#039;:&#039;ปิด&#039;,&lt;br /&gt;
   &#039;ti&#039;:&#039;ዕጸው&#039;,&lt;br /&gt;
   &#039;tr&#039;:&#039;kapat&#039;,&lt;br /&gt;
   &#039;uk&#039;:&#039;закрити&#039;,&lt;br /&gt;
   &#039;vi&#039;:&#039;đóng&#039;,&lt;br /&gt;
   &#039;vo&#039;:&#039;färmükön&#039;,&lt;br /&gt;
   &#039;zh&#039;:&#039;关闭&#039;,&lt;br /&gt;
   &#039;zh-cn&#039;:&#039;关闭&#039;,&lt;br /&gt;
   &#039;zh-hk&#039;:&#039;關閉&#039;,&lt;br /&gt;
   &#039;zh-sg&#039;:&#039;关闭&#039;,&lt;br /&gt;
   &#039;zh-tw&#039;:&#039;關閉&#039;,&lt;br /&gt;
   &#039;zh-yue&#039;:&#039;收埋&#039;&lt;br /&gt;
  },&lt;br /&gt;
  resize : {&lt;br /&gt;
   &#039;ar&#039;:&#039;تغيير حجم&#039;,&lt;br /&gt;
   &#039;ast&#039;:&#039;redimensionar&#039;,&lt;br /&gt;
   &#039;az&#039;:&#039;ölçüləri dəyiş&#039;,&lt;br /&gt;
   &#039;bg&#039;:&#039;Промени големина&#039;,&lt;br /&gt;
   &#039;bn&#039;:&#039;মাপ পরিবর্তন করুন&#039;,&lt;br /&gt;
   &#039;bs&#039;:&#039;promijeni veličinu&#039;,&lt;br /&gt;
   &#039;ca&#039;:&#039;Redimensiona&#039;,&lt;br /&gt;
   &#039;cs&#039;:&#039;změnit velikost&#039;,&lt;br /&gt;
   &#039;de&#039;:&#039;Größe ändern&#039;,&lt;br /&gt;
   &#039;dk&#039;:&#039;ændre størrelse&#039;,&lt;br /&gt;
   &#039;el&#039;:&#039;αλλαγή μεγέθους&#039;,&lt;br /&gt;
   &#039;en&#039;:&#039;resize&#039;,&lt;br /&gt;
   &#039;es&#039;:&#039;cambiar el tamaño&#039;,&lt;br /&gt;
   &#039;fa&#039;:&#039;تغییر اندازه&#039;,&lt;br /&gt;
   &#039;fi&#039;:&#039;muuta kokoa&#039;,&lt;br /&gt;
   &#039;fr&#039;:&#039;redimensionner&#039;,&lt;br /&gt;
   &#039;gl&#039;:&#039;cambiar o tamaño&#039;,&lt;br /&gt;
   &#039;hr&#039;:&#039;promijeni veličinu&#039;,&lt;br /&gt;
   &#039;hu&#039;:&#039;átméretezés&#039;,&lt;br /&gt;
   &#039;ilo&#039;:&#039;baliwan ti kadakkel&#039;,&lt;br /&gt;
   &#039;it&#039;:&#039;ridimensiona&#039;,&lt;br /&gt;
   &#039;ja&#039;:&#039;サイズを変更する&#039;,&lt;br /&gt;
   &#039;kk&#039;:&#039;өлшемін өзгерту&#039;,&lt;br /&gt;
   &#039;kn&#039;:&#039;ಗಾತ್ರ ಬದಲಿಸು&#039;,&lt;br /&gt;
   &#039;min&#039;:&#039;gadangan&#039;,&lt;br /&gt;
   &#039;mk&#039;:&#039;промени големина&#039;,&lt;br /&gt;
   &#039;ml&#039;:&#039;വലിപ്പം മാറ്റുക&#039;,&lt;br /&gt;
   &#039;ms&#039;:&#039;ubah saiz&#039;,&lt;br /&gt;
   &#039;my&#039;:&#039;အရွယ်အစားညှိရန်&#039;,&lt;br /&gt;
   &#039;nl&#039;:&#039;vergroten of verkleinen&#039;,&lt;br /&gt;
   &#039;no&#039;:&#039;endre størrelse&#039;,&lt;br /&gt;
   &#039;ps&#039;:&#039;د کچې بدلول&#039;,&lt;br /&gt;
   &#039;pt&#039;:&#039;alterar tamanho&#039;,&lt;br /&gt;
   &#039;ro&#039;:&#039;redimensionare&#039;,&lt;br /&gt;
   &#039;sh&#039;:&#039;promijeni veličinu&#039;,&lt;br /&gt;
   &#039;sl&#039;:&#039;spremeni velikost&#039;,&lt;br /&gt;
   &#039;sr&#039;:&#039;промени величину&#039;,&lt;br /&gt;
   &#039;sr-ec&#039;:&#039;промени величину&#039;,&lt;br /&gt;
   &#039;sr-el&#039;:&#039;promeni veličinu&#039;,&lt;br /&gt;
   &#039;sv&#039;:&#039;ändra storlek&#039;,&lt;br /&gt;
   &#039;th&#039;:&#039;ปรับขนาด&#039;,&lt;br /&gt;
   &#039;ti&#039;:&#039;መጠን ለውጥ&#039;,&lt;br /&gt;
   &#039;uk&#039;:&#039;змінити розмір&#039;,&lt;br /&gt;
   &#039;zh&#039;:&#039;调整大小&#039;,&lt;br /&gt;
   &#039;zh-cn&#039;:&#039;调整大小&#039;,&lt;br /&gt;
   &#039;zh-hk&#039;:&#039;調整大小&#039;,&lt;br /&gt;
   &#039;zh-sg&#039;:&#039;调整大小&#039;,&lt;br /&gt;
   &#039;zh-tw&#039;:&#039;調整大小&#039;,&lt;br /&gt;
   &#039;zh-yue&#039;:&#039;改大細&#039;&lt;br /&gt;
  }&lt;br /&gt;
 },&lt;br /&gt;
 // domain of the WMA&lt;br /&gt;
 wma_domain = &#039;//wma.wmcloud.org&#039;,&lt;br /&gt;
&lt;br /&gt;
 language = &#039;&#039;, site = &#039;&#039;, awt=&#039;0&#039;, rtl = /(^|\s)rtl(\s|$)/.test(document.body.className),&lt;br /&gt;
&lt;br /&gt;
 // Get a specific, localized string&lt;br /&gt;
 _msg = function(k) {&lt;br /&gt;
  return strings[k][language] || strings[k].en;&lt;br /&gt;
 },&lt;br /&gt;
 dbName = mw.config.get( &#039;wgDBname&#039; ),&lt;br /&gt;
&lt;br /&gt;
 iframe = { div: null, iframe: null, closebutton: null, resizebutton: null, resizehelper: null, indom: false },&lt;br /&gt;
&lt;br /&gt;
 page_title = ( mw.config.get(&#039;wgNamespaceNumber&#039;)===0 ) ? encodeURIComponent(mw.config.get(&#039;wgTitle&#039;)) : &#039;&#039;,&lt;br /&gt;
&lt;br /&gt;
 bodyc,&lt;br /&gt;
 coord_filter = /[?&amp;amp;]params=([\d.+-]+)_([\d.+-]*)_?([\d.+-]*)_?([NSZ])_([\d.+-]+)_([\d.+-]*)_?([\d.+-]*)_?([EOW])([^&amp;amp;=&amp;lt;&amp;gt;|]{0,250})/,&lt;br /&gt;
 coord_list = [],&lt;br /&gt;
 coord_highlight = -1,&lt;br /&gt;
&lt;br /&gt;
 kml = null,&lt;br /&gt;
 mes = null,&lt;br /&gt;
 initPromises = [];&lt;br /&gt;
&lt;br /&gt;
 // get position on page&lt;br /&gt;
 function yPos(el) {&lt;br /&gt;
  return $(el).offset().top + $(el).outerHeight();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 // show, move, and update iframe&lt;br /&gt;
 function showIFrame(e) {&lt;br /&gt;
  var wi = iframe, my = yPos(this),&lt;br /&gt;
      newurl = wc.iframeurl + &#039;?wma=&#039; + e.data.param + &#039;&amp;amp;lang=&#039; + site + &#039;&amp;amp;page=&#039; + page_title + &#039;&amp;amp;awt=&#039; + awt;&lt;br /&gt;
&lt;br /&gt;
  // insert iframe into DOM on demand (to preserve page caching)&lt;br /&gt;
  if (!wi.indom) {&lt;br /&gt;
   $(&#039;#content,#mw_content&#039;).prepend(wi.div);&lt;br /&gt;
   wi.indom = true;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if (wi.iframe.attr(&#039;src&#039;)!==newurl) {&lt;br /&gt;
   wi.iframe.attr( &#039;src&#039;, newurl );&lt;br /&gt;
  } else if( wi.div.css(&#039;display&#039;) !== &#039;none&#039; ) {&lt;br /&gt;
   wi.div.hide();&lt;br /&gt;
   return false;&lt;br /&gt;
  }&lt;br /&gt;
  wi.div.css( &#039;top&#039;, my+&#039;px&#039; ).show();&lt;br /&gt;
  return false;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 function highlight(i) {&lt;br /&gt;
  if (coord_highlight&amp;gt;=0) {&lt;br /&gt;
   $(coord_list[coord_highlight].obj).css(&#039;background-color&#039;,&#039;&#039;).find(&#039;span:visible&#039;).css(&#039;background-color&#039;,&#039;&#039;);&lt;br /&gt;
  }&lt;br /&gt;
  coord_highlight = i;&lt;br /&gt;
  if (coord_highlight&amp;gt;=0) {&lt;br /&gt;
   $(coord_list[coord_highlight].obj).css(&#039;background-color&#039;,&#039;yellow&#039;).find(&#039;span:visible&#039;).css(&#039;background-color&#039;,&#039;yellow&#039;);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 function messageHub(e) {&lt;br /&gt;
  var i, d, clist = { coords: [] }&lt;br /&gt;
    , geoext = [], sx=0, sy=0, s&lt;br /&gt;
    , minlat = Infinity, maxlat = -Infinity, ineg = -1, ipos = -1;&lt;br /&gt;
  e = e.originalEvent;&lt;br /&gt;
  if (!e || !e.data || !e.data.split) {&lt;br /&gt;
    // avoid  Uncaught TypeError: e.data.split is not a function&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
  d = e.data.split(&#039;,&#039;);&lt;br /&gt;
  mes = e.source;&lt;br /&gt;
  switch(d[0]) {&lt;br /&gt;
   case &#039;request&#039; :&lt;br /&gt;
    // make a JSON encodable copy of coord_list (no HTML objects!)&lt;br /&gt;
    // find center and extent&lt;br /&gt;
    for (i=0; i&amp;lt;coord_list.length; ++i) {&lt;br /&gt;
     clist.coords[i] = {&lt;br /&gt;
      lat: coord_list[i].lat,&lt;br /&gt;
      lon: coord_list[i].lon,&lt;br /&gt;
      title: coord_list[i].title.replace(/[\+_]/g,&#039; &#039;)&lt;br /&gt;
     };&lt;br /&gt;
     if (coord_list[i].lat&amp;lt;minlat) { minlat = coord_list[i].lat; }&lt;br /&gt;
     if (coord_list[i].lat&amp;gt;maxlat) { maxlat = coord_list[i].lat; }&lt;br /&gt;
     geoext[i] = {&lt;br /&gt;
      x: Math.cos(coord_list[i].lon/180.0*Math.PI),&lt;br /&gt;
      y: Math.sin(coord_list[i].lon/180.0*Math.PI)&lt;br /&gt;
     };&lt;br /&gt;
     sx += geoext[i].x;&lt;br /&gt;
     sy += geoext[i].y;&lt;br /&gt;
    }&lt;br /&gt;
    clist.loncenter = Math.atan2(sy,sx)*180.0/Math.PI;&lt;br /&gt;
    clist.latmax = maxlat;&lt;br /&gt;
    clist.latmin = minlat;&lt;br /&gt;
    // extent in longitude&lt;br /&gt;
    for (i=0; i&amp;lt;geoext.length; ++i) {&lt;br /&gt;
     s = (geoext[i].x*sy-geoext[i].y*sx);&lt;br /&gt;
     geoext[i].z = (geoext[i].x*sx+geoext[i].y*sy);&lt;br /&gt;
     if (s&amp;lt;0 &amp;amp;&amp;amp; (ineg&amp;lt;0 || geoext[i].z&amp;lt;geoext[ineg].z)) { ineg=i; }&lt;br /&gt;
     if (s&amp;gt;0 &amp;amp;&amp;amp; (ipos&amp;lt;0 || geoext[i].z&amp;lt;geoext[ipos].z)) { ipos=i; }&lt;br /&gt;
    }&lt;br /&gt;
    if (ipos&amp;gt;=0 &amp;amp;&amp;amp; ineg&amp;gt;=0) {&lt;br /&gt;
     clist.lonleft  = coord_list[ipos].lon;&lt;br /&gt;
     clist.lonright = coord_list[ineg].lon;&lt;br /&gt;
    }&lt;br /&gt;
    if (&#039;JSON&#039; in window) {&lt;br /&gt;
     mes.postMessage(JSON.stringify(clist), document.location.protocol + wma_domain);&lt;br /&gt;
     if (kml!==null) {&lt;br /&gt;
      mes.postMessage(JSON.stringify(kml), document.location.protocol + wma_domain);&lt;br /&gt;
     }&lt;br /&gt;
    }&lt;br /&gt;
    break;&lt;br /&gt;
   case &#039;unhighlight&#039; :&lt;br /&gt;
    highlight(-1);&lt;br /&gt;
    break;&lt;br /&gt;
   case &#039;toggle&#039; :&lt;br /&gt;
    coord_list[parseInt(d[1],10)].mb.click();&lt;br /&gt;
    break;&lt;br /&gt;
   case &#039;scroll&#039; :&lt;br /&gt;
    $(&#039;html:not(:animated),body:not(:animated)&#039;).animate({ scrollTop: $(coord_list[parseInt(d[1],10)].obj).offset().top - 20 + parseInt(d[2]||&#039;0&#039;,10) }, 500 );&lt;br /&gt;
    iframe.div.css( { top: yPos( coord_list[parseInt(d[1],10)].obj ) + &#039;px&#039;} );&lt;br /&gt;
    // make sure scroll target gets highlighted&lt;br /&gt;
    setTimeout(function () { highlight(parseInt(d[1],10)); }, 200);&lt;br /&gt;
    break;&lt;br /&gt;
   case &#039;highlight&#039; :&lt;br /&gt;
    highlight(parseInt(d[1],10));&lt;br /&gt;
    break;&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 // parse url parameters into a hash&lt;br /&gt;
 function parseParams(url) {&lt;br /&gt;
  var map = {}, h, i, pair = url.substr(url.indexOf(&#039;?&#039;)+1).split(&#039;&amp;amp;&#039;);&lt;br /&gt;
  for (i=0; i&amp;lt;pair.length; ++i) {&lt;br /&gt;
   h = pair[i].split(&#039;=&#039;);&lt;br /&gt;
   map[h[0]] = h[1];&lt;br /&gt;
  }&lt;br /&gt;
  return map;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 // Insert the IFrame into the page.&lt;br /&gt;
&lt;br /&gt;
 var wi = iframe,&lt;br /&gt;
     marker = { lat:0, lon:0 }, coordinates = null,&lt;br /&gt;
     links, key, startTime, mapbutton;&lt;br /&gt;
&lt;br /&gt;
 // apply settings&lt;br /&gt;
 if (typeof wma_settings===&#039;object&#039;) {&lt;br /&gt;
  for (key in wma_settings) {&lt;br /&gt;
   if (typeof wma_settings[key]===typeof wc[key]) { wc[key] = wma_settings[key]; }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 if (wc.enabled===false) { return; }&lt;br /&gt;
&lt;br /&gt;
 site = (dbName===&#039;commonswiki&#039;) ? &#039;commons&#039; : (mw.config.get(&#039;wgUserVariant&#039;) || mw.config.get(&#039;wgPageContentLanguage&#039;));&lt;br /&gt;
 language = mw.config.get( &#039;wgUserLanguage&#039; );&lt;br /&gt;
&lt;br /&gt;
 // bhwiki reports bho as language. I do not understand that yet, so let&#039;s add an exception&lt;br /&gt;
 if (site === &#039;bho&#039;) site = &#039;bh&#039;;&lt;br /&gt;
&lt;br /&gt;
 // remove icons from title coordinates&lt;br /&gt;
 $(&#039;#coordinates,#coordinates-title,#tpl_Coordinaten&#039;).find(&#039;a.image, span[typeof*=&amp;quot;mw:File&amp;quot;]&#039;).detach();&lt;br /&gt;
&lt;br /&gt;
 bodyc = $( wc.onlytitle ? &#039;#coordinates,#coordinates-title&#039; : &#039;html&#039; );&lt;br /&gt;
 startTime = (new Date()).getTime();&lt;br /&gt;
&lt;br /&gt;
 bodyc.find(&#039;a.external.text&#039;).each( function( key, link ) {&lt;br /&gt;
  var ws, coord_params, params, zoomlevel, globe=&#039;Earth&#039;;&lt;br /&gt;
&lt;br /&gt;
  // check for timeout (every 10 links only)&lt;br /&gt;
  if (key%10===9 &amp;amp;&amp;amp; (new Date()).getTime() &amp;gt; startTime+wc.timeout) {&lt;br /&gt;
   return false; // break out of each&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if (!(&#039;href&#039; in link) || !coord_filter.exec(link.href)) { // invalid links do not contain href attribute in IE!&lt;br /&gt;
   return true;&lt;br /&gt;
  }&lt;br /&gt;
  marker.lat=(1.0*RegExp.$1) + ((RegExp.$2||0)/60.0) + ((RegExp.$3||0)/3600.0);&lt;br /&gt;
  if (RegExp.$4!==&#039;N&#039;) { marker.lat*=-1; }&lt;br /&gt;
  marker.lon=(1.0*RegExp.$5) + ((RegExp.$6||0)/60.0) + ((RegExp.$7||0)/3600.0);&lt;br /&gt;
  if (RegExp.$8===&#039;W&#039;) { marker.lon*=-1; }&lt;br /&gt;
  coord_params = RegExp.$9;&lt;br /&gt;
&lt;br /&gt;
  // Zoom based on coordinate N/S precision&lt;br /&gt;
  var coord_digits = RegExp.$3 ? 4 : RegExp.$2 ? 2 : RegExp.$1.length - (RegExp.$1+&#039;.&#039;).indexOf(&#039;.&#039;) - 1;&lt;br /&gt;
  zoomlevel = coord_digits * Math.log(10)/Math.log(2);&lt;br /&gt;
&lt;br /&gt;
  // Find a sensible Zoom-level based on type&lt;br /&gt;
  if( /_type:(airport|edu|pass|landmark|railwaystation)/.test(coord_params) ) {&lt;br /&gt;
   zoomlevel = 8;&lt;br /&gt;
  } else if (/_type:(event|forest|glacier)/.test(coord_params)) {&lt;br /&gt;
   zoomlevel = 6;&lt;br /&gt;
  } else if (/_type:(adm3rd|city|mountain|isle|river|waterbody)/.test(coord_params)) {&lt;br /&gt;
   zoomlevel = 4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // wma shows dim approx 4e7m at zoom 0 or 1.5e8 is the scale of zoomlevel 0&lt;br /&gt;
  if (/_dim:([\d.+-]+)(km|m|_|$)/.exec(coord_params)) {&lt;br /&gt;
   zoomlevel = Math.log((RegExp.$2===&#039;km&#039; ? 4e4 : 4e7) / RegExp.$1)/Math.log(2);&lt;br /&gt;
  }&lt;br /&gt;
  if (/_scale:(\d+)(_|$)/.exec(coord_params)) {&lt;br /&gt;
   zoomlevel = Math.log(1.5e8/RegExp.$1) / Math.log(2);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if (wc.zoom!==-1) { zoomlevel = wc.zoom; }&lt;br /&gt;
  //if( zoomlevel &amp;gt; 12 ) { zoomlevel = 12; }&lt;br /&gt;
  if (zoomlevel&amp;lt;0) { zoomlevel = 0; }&lt;br /&gt;
&lt;br /&gt;
  function capitalize(s) { return s.substr(0,1).toUpperCase()+s.substr(1).toLowerCase(); }&lt;br /&gt;
  if (/_globe:([^_&amp;amp;]+)/.test(coord_params)) { globe = capitalize(RegExp.$1); }&lt;br /&gt;
  if ($.inArray(globe,[&#039;Earth&#039;,&#039;Moon&#039;,&#039;Mars&#039;,&#039;Venus&#039;,&#039;Mercury&#039;,&#039;Io&#039;,&#039;Titan&#039;]) &amp;lt; 0 ) { return; }&lt;br /&gt;
&lt;br /&gt;
  // Test the unicode Symbol&lt;br /&gt;
  if (site===&#039;de&#039; &amp;amp;&amp;amp; link.parentNode.id!==&#039;coordinates&#039;) {&lt;br /&gt;
   mapbutton = $(&#039;&amp;lt;span&amp;gt;♁&amp;lt;/span&amp;gt;&#039;).css(&#039;color&#039;,&#039;blue&#039;);&lt;br /&gt;
  } else {&lt;br /&gt;
   mapbutton = $(&#039;&amp;lt;img&amp;gt;&#039;).attr(&#039;src&#039;, wc.buttonImage).attr(&#039;srcset&#039;, wc.buttonImage + &#039; 1x, &#039; + wc.buttonImage2x + &#039; 2x&#039;)&lt;br /&gt;
    .attr(&#039;width&#039;, wc.buttonWidth).attr(&#039;height&#039;, wc.buttonHeight);&lt;br /&gt;
  }&lt;br /&gt;
  mapbutton.addClass(&#039;wmamapbutton noprint&#039;).attr( {&lt;br /&gt;
   title: _msg(&#039;buttonTooltip&#039;),&lt;br /&gt;
   alt: &#039;&#039;&lt;br /&gt;
  } )&lt;br /&gt;
  .on(&#039;mouseenter&#039;, function (){ $(this).css(&#039;opacity&#039;, 0.75); })&lt;br /&gt;
  .on(&#039;mouseleave&#039;, function () { $(this).css(&#039;opacity&#039;, &#039;&#039;); })&lt;br /&gt;
  .css(&#039;padding&#039;, rtl ? &#039;0px 0px 0px 3px&#039; : &#039;0px 3px 0px 0px&#039; ).css(&#039;cursor&#039;, &#039;pointer&#039;);&lt;br /&gt;
&lt;br /&gt;
  if (wc.alwaysTooltips || ( wc.flowTextTooltips &amp;amp;&amp;amp; $(link).parents(&#039;li, table, #coordinates&#039;).length===0)) {&lt;br /&gt;
   // insert tooltip rather than icon to improve text readability&lt;br /&gt;
   mapbutton = $(&#039;&amp;lt;span&amp;gt;&#039;).append(mapbutton).append(&#039;&amp;amp;nbsp;WikiMiniAtlas&#039;).css(&#039;cursor&#039;,&#039;pointer&#039;);&lt;br /&gt;
   var tooltip = $(&#039;&amp;lt;div&amp;gt;&#039;).css( {&lt;br /&gt;
    backgroundColor: &#039;white&#039;, padding: &#039;0.2em&#039;, border: &#039;1px solid black&#039;,&lt;br /&gt;
    position: &#039;absolute&#039;, top: &#039;1em&#039;, left: &#039;0em&#039;,&lt;br /&gt;
    display: &#039;none&#039;, zIndex : 15&lt;br /&gt;
   }).append(mapbutton);&lt;br /&gt;
   $(link).wrap(&lt;br /&gt;
    $(&#039;&amp;lt;span&amp;gt;&#039;)&lt;br /&gt;
     .css( { position: &#039;relative&#039;, whiteSpace: &#039;nowrap&#039; } )&lt;br /&gt;
     .on(&#039;mouseleave&#039;, function () { tooltip.fadeOut(); })&lt;br /&gt;
    )&lt;br /&gt;
    .before(tooltip)&lt;br /&gt;
    .on(&#039;mouseenter&#039;, function () { tooltip.fadeIn(); });&lt;br /&gt;
  } else {&lt;br /&gt;
   // insert icon directly&lt;br /&gt;
   ws = $(link).css(&#039;whiteSpace&#039;);&lt;br /&gt;
   if (site!==&#039;de&#039; || link.parentNode.id!==&#039;coordinates&#039;) {&lt;br /&gt;
    $(link).wrap( $(&#039;&amp;lt;span&amp;gt;&#039;).css(&#039;whiteSpace&#039;, &#039;nowrap&#039;) ).css(&#039;whiteSpace&#039;, ws).before(mapbutton);&lt;br /&gt;
   } else {&lt;br /&gt;
    $(&#039;#coordinates&#039;).append(&#039;&amp;lt;span class=&amp;quot;noprint coordinates-separator&amp;quot;&amp;gt; | &amp;lt;/span&amp;gt;&#039;).append(mapbutton);&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  mapbutton.on( &#039;click&#039;, { param:&lt;br /&gt;
   marker.lat + &#039;_&#039; + marker.lon + &#039;_&#039; +&lt;br /&gt;
   wc.width + &#039;_&#039; + wc.height + &#039;_&#039; +&lt;br /&gt;
   site + &#039;_&#039; + zoomlevel + &#039;_&#039; + language + &#039;&amp;amp;globe=&#039; + globe }, showIFrame );&lt;br /&gt;
&lt;br /&gt;
  // store coordinates&lt;br /&gt;
  coordinates = link.href;&lt;br /&gt;
  params = parseParams(link.href);&lt;br /&gt;
  coord_list.push( { lat: marker.lat, lon: marker.lon, obj: link, mb: mapbutton, title: params.title || params.pagename || &#039;&#039; } );&lt;br /&gt;
 } ); //end each&lt;br /&gt;
&lt;br /&gt;
 var titlebutton = false;&lt;br /&gt;
&lt;br /&gt;
 function addTitleButton( alat, alon, zoomlevel ) {&lt;br /&gt;
  mapbutton = $(&#039;&amp;lt;img&amp;gt;&#039;)&lt;br /&gt;
   .on(&#039;mouseenter&#039;, function (){ $(this).css(&#039;opacity&#039;, 0.75); })&lt;br /&gt;
   .on(&#039;mouseleave&#039;, function () { $(this).css(&#039;opacity&#039;, &#039;&#039;); })&lt;br /&gt;
   .css(&#039;padding&#039;, rtl ? &#039;0px 3px 0px 0px&#039; : &#039;0px 0px 0px 3px&#039; ).css(&#039;cursor&#039;, &#039;pointer&#039;)&lt;br /&gt;
   .attr(&#039;src&#039;, wc.buttonImage).attr(&#039;srcset&#039;, wc.buttonImage + &#039; 1x, &#039; + wc.buttonImage2x + &#039; 2x&#039;)&lt;br /&gt;
   .attr(&#039;width&#039;, wc.buttonWidth).attr(&#039;height&#039;, wc.buttonHeight)&lt;br /&gt;
   .addClass(&#039;wmamapbutton noprint&#039;)&lt;br /&gt;
   .on( &#039;click&#039;, { param:&lt;br /&gt;
    alat + &#039;_&#039; + alon + &#039;_&#039; +&lt;br /&gt;
    wc.width + &#039;_&#039; + wc.height + &#039;_&#039; +&lt;br /&gt;
    site + &#039;_&#039; + zoomlevel + &#039;_&#039; + language&lt;br /&gt;
   }, showIFrame ); // zoomlevel!&lt;br /&gt;
&lt;br /&gt;
  if (!titlebutton) {&lt;br /&gt;
   if ($(&#039;#coordinates&#039;).length) {&lt;br /&gt;
    $(&#039;#coordinates&#039;).find(&#039;img&#039;).detach();&lt;br /&gt;
    $(&#039;#coordinates&#039;).append(mapbutton);&lt;br /&gt;
   } else {&lt;br /&gt;
    $(&#039;&amp;lt;span id=&amp;quot;coordinates&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;).text(_msg(&#039;map&#039;)).append(mapbutton).appendTo(&#039;#bodyContent&#039;);&lt;br /&gt;
   }&lt;br /&gt;
   titlebutton = true;&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 // detect and load KML&lt;br /&gt;
 // also insert globe even if no title coords are given&lt;br /&gt;
 (function () {&lt;br /&gt;
  var i, l = $(&#039;div.kmldata&#039;)&lt;br /&gt;
     ,alat = 0, alon = 0&lt;br /&gt;
     ,la1 = Infinity, la2 =- Infinity&lt;br /&gt;
     ,lo1 = Infinity, lo2 =- Infinity&lt;br /&gt;
     ,ex,ey, req;&lt;br /&gt;
&lt;br /&gt;
  for (i=0; i&amp;lt;l.length; ++i) {// TODO: replace with .each&lt;br /&gt;
   coordinates = true;&lt;br /&gt;
   req = $.ajax({&lt;br /&gt;
    url: &#039;/wiki/&#039; + encodeURI(l.eq(i).attr(&#039;title&#039;)) + &#039;?action=raw&#039;,&lt;br /&gt;
    dataType: &#039;xml&#039;,&lt;br /&gt;
    success: function (xml) {&lt;br /&gt;
     var zoomlevel;&lt;br /&gt;
&lt;br /&gt;
     function processCoords(t) {&lt;br /&gt;
      var way = [], c, p = t.split(&#039; &#039;), i, lat, lon;&lt;br /&gt;
      for( i=0; i&amp;lt;p.length; ++i ) {&lt;br /&gt;
       c=p[i].split(&#039;,&#039;);&lt;br /&gt;
       if( c.length &amp;gt;= 2 ) {&lt;br /&gt;
        lat = parseFloat(c[1]);&lt;br /&gt;
        lon = parseFloat(c[0]);&lt;br /&gt;
        way.push( { lat: lat, lon: lon } );&lt;br /&gt;
&lt;br /&gt;
        // determine extent of way&lt;br /&gt;
        if (lat&amp;lt;la1) { la1=lat; }&lt;br /&gt;
        if (lon&amp;lt;lo1) { lo1=lon; }&lt;br /&gt;
        if (lat&amp;gt;la2) { la2=lat; }&lt;br /&gt;
        if (lon&amp;gt;lo2) { lo2=lon; }&lt;br /&gt;
       }&lt;br /&gt;
      }&lt;br /&gt;
      return way;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // initialize transfer datastructure&lt;br /&gt;
     kml = { ways: [], areas: [] };&lt;br /&gt;
&lt;br /&gt;
     // ways&lt;br /&gt;
     $(xml).find(&#039;LineString &amp;gt; coordinates&#039;).each(function () {&lt;br /&gt;
      var way = processCoords( $(this).text() );&lt;br /&gt;
      if (way.length&amp;gt;0) { kml.ways.push(way); }&lt;br /&gt;
     });&lt;br /&gt;
&lt;br /&gt;
     // areas&lt;br /&gt;
     $(xml).find(&#039;Polygon&#039;).each(function () {&lt;br /&gt;
      var area = { inner: [], outer: [] };&lt;br /&gt;
&lt;br /&gt;
      // outer boundary&lt;br /&gt;
      $(this).find(&#039;outerBoundaryIs &amp;gt; LinearRing &amp;gt; coordinates&#039;).each(function () {&lt;br /&gt;
       var way = processCoords($(this).text());&lt;br /&gt;
       if (way.length&amp;gt;0) { area.outer.push(way); }&lt;br /&gt;
      });&lt;br /&gt;
&lt;br /&gt;
      // inner boundary (holes in the polygon)&lt;br /&gt;
      $(this).find(&#039;innerBoundaryIs &amp;gt; LinearRing &amp;gt; coordinates&#039;).each(function () {&lt;br /&gt;
       var way = processCoords($(this).text());&lt;br /&gt;
       if (way.length&amp;gt;0) { area.inner.push(way); }&lt;br /&gt;
      });&lt;br /&gt;
&lt;br /&gt;
      // only add if we have an outer boundary&lt;br /&gt;
      if (area.outer.length&amp;gt;0) { kml.areas.push(area); }&lt;br /&gt;
     });&lt;br /&gt;
&lt;br /&gt;
     // inset min/max extent&lt;br /&gt;
     kml.minlon = lo1;&lt;br /&gt;
     kml.maxlon = lo2;&lt;br /&gt;
     kml.minlat = la1;&lt;br /&gt;
     kml.maxlat = la2;&lt;br /&gt;
&lt;br /&gt;
     // already got a request message&lt;br /&gt;
     if (mes!==null &amp;amp;&amp;amp; kml.ways.length&amp;gt;0 &amp;amp;&amp;amp; &#039;JSON&#039; in window) {&lt;br /&gt;
      mes.postMessage(JSON.stringify(kml), document.location.protocol + wma_domain);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // insert blue globe&lt;br /&gt;
     if (coord_list.length===0 || (!$(&#039;#coordinates&#039;).find(&#039;.wmamapbutton&#039;).length)) {&lt;br /&gt;
      // determine center&lt;br /&gt;
      alat = (la1+la2)/2;&lt;br /&gt;
      alon = (lo1+lo2)/2;&lt;br /&gt;
&lt;br /&gt;
      //determine zoomfactor&lt;br /&gt;
      ex = (lo2-lo1)/180.0 * 3.0*128;&lt;br /&gt;
      ey = (la2-la1)/180.0 * 3.0*128; // max extent in degrees, zoom0 has 3*128/180 px/degree&lt;br /&gt;
      for (zoomlevel=0; zoomlevel&amp;lt;12; ++zoomlevel) {&lt;br /&gt;
       if( ex&amp;gt;wc.width/2 || ey&amp;gt;wc.height/2 ) break;&lt;br /&gt;
       ex *= 2; ey *= 2;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // add mapbutton&lt;br /&gt;
      addTitleButton( alat, alon, zoomlevel );&lt;br /&gt;
     }&lt;br /&gt;
    }&lt;br /&gt;
   });&lt;br /&gt;
   // Add request promise to init array, and cast any errors to success so that&lt;br /&gt;
   // we don&#039;t abort init early when one of the requests failed. These are expected&lt;br /&gt;
   // to fail for titles we can&#039;t find.&lt;br /&gt;
   initPromises.push(req.then(null, function () { return $.Deferred().resolve(); } ));&lt;br /&gt;
  } // end for&lt;br /&gt;
 })();&lt;br /&gt;
&lt;br /&gt;
 // detect &amp;quot;All Coordinates&amp;quot;&lt;br /&gt;
 links = $(&#039;#coordinates&amp;gt;span&amp;gt;a&#039;);&lt;br /&gt;
 if (links.length &amp;amp;&amp;amp; links[0].href.indexOf(&#039;http://www.lenz-online.de/cgi-bin/wiki/wiki-osm.pl&#039;) === 0) {&lt;br /&gt;
   addTitleButton( 0, 0, 1 );&lt;br /&gt;
   coordinates = true;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 // prepare iframe to house the map&lt;br /&gt;
 if (coordinates!==null) {&lt;br /&gt;
  wi.div = $(&#039;&amp;lt;div&amp;gt;&#039;).css( {&lt;br /&gt;
   width: (wc.width+2)+&#039;px&#039;, height: (wc.height+2)+&#039;px&#039;,&lt;br /&gt;
   margin: &#039;0px&#039;, padding: &#039;0px&#039;,&lt;br /&gt;
   backgroundColor : &#039;white&#039;, border: &#039;1px solid gray&#039;,&lt;br /&gt;
   position: &#039;absolute&#039;, top: &#039;1em&#039;, zIndex: 13, boxShadow: &#039;3px 3px 25px rgba(0,0,0,0.3)&#039;&lt;br /&gt;
  } ).css( rtl ? &#039;left&#039; : &#039;right&#039;, &#039;2em&#039; ).hide();&lt;br /&gt;
&lt;br /&gt;
  var rbrtl = [ &#039;//upload.wikimedia.org/wikipedia/commons/b/b5/Button_resize.png&#039;,&lt;br /&gt;
                &#039;//upload.wikimedia.org/wikipedia/commons/3/30/Button_resize_rtl.png&#039; ];&lt;br /&gt;
  wi.resizebutton = $(&#039;&amp;lt;img&amp;gt;&#039;).attr( {&lt;br /&gt;
   title : _msg(&#039;resize&#039;),&lt;br /&gt;
   src : rbrtl[rtl?1:0]&lt;br /&gt;
  } ).hide().attr(&#039;ondragstart&#039;,&#039;return false&#039;);&lt;br /&gt;
&lt;br /&gt;
  // cover the iframe to prevent loosing the mouse to the iframe during resizing&lt;br /&gt;
  wi.resizehelper = $(&#039;&amp;lt;div&amp;gt;&#039;).css( { position: &#039;absolute&#039;, top:0, left:0, zIndex: 20 } ).hide();&lt;br /&gt;
&lt;br /&gt;
  wi.closebutton = $(&#039;&amp;lt;img&amp;gt;&#039;).attr( {&lt;br /&gt;
   title : _msg(&#039;close&#039;),&lt;br /&gt;
   src : &#039;//upload.wikimedia.org/wikipedia/commons/d/d4/Button_hide.png&#039;&lt;br /&gt;
  } ).css( {&lt;br /&gt;
   zIndex : 15, position : &#039;absolute&#039;, right : &#039;11px&#039;, top : &#039;9px&#039;, width : &#039;18px&#039;, cursor : &#039;pointer&#039;&lt;br /&gt;
  } ).click( function(e) { wi.div.hide(); } );&lt;br /&gt;
&lt;br /&gt;
  wi.iframe = $(&#039;&amp;lt;iframe&amp;gt;&#039;)&lt;br /&gt;
   .attr( { scrolling: &#039;no&#039;, frameBorder : 0 } )&lt;br /&gt;
   .css( {&lt;br /&gt;
    zIndex: 14, position: &#039;absolute&#039;, right: &#039;1px&#039;, top: &#039;1px&#039;,&lt;br /&gt;
    width: (wc.width)+&#039;px&#039;, height: (wc.height)+&#039;px&#039;,&lt;br /&gt;
    margin: &#039;0px&#039;, padding: &#039;0px&#039;&lt;br /&gt;
   } );&lt;br /&gt;
&lt;br /&gt;
  wi.div.append(wi.iframe);&lt;br /&gt;
  wi.div.append(wi.resizehelper);&lt;br /&gt;
  wi.div.append(wi.closebutton);&lt;br /&gt;
  (function () {&lt;br /&gt;
   var idle = true, dir = rtl?-1:1;&lt;br /&gt;
   function adjusthelper() {&lt;br /&gt;
    wi.resizehelper.css( { width: (wc.width+2)+&#039;px&#039;, height: (wc.height+2)+&#039;px&#039; } );&lt;br /&gt;
   }&lt;br /&gt;
   wi.div.append(&lt;br /&gt;
    $(&#039;&amp;lt;div&amp;gt;&#039;)&lt;br /&gt;
     .css( {&lt;br /&gt;
       zIndex : 15, position : &#039;absolute&#039;, bottom : &#039;3px&#039;,&lt;br /&gt;
       width : &#039;18px&#039;, height: &#039;18px&#039;, cursor : (rtl?&#039;se-resize&#039;:&#039;sw-resize&#039;),&lt;br /&gt;
       &#039;user-select&#039;: &#039;none&#039;, &#039;-moz-user-select&#039;: &#039;none&#039;, &#039;-ms-user-select&#039;: &#039;none&#039;&lt;br /&gt;
      } ).css( (rtl?&#039;right&#039;:&#039;left&#039;), &#039;3px&#039; )&lt;br /&gt;
     .on(&#039;mouseenter&#039;, function(e) { wi.resizebutton.fadeIn(); } )&lt;br /&gt;
     .on(&#039;mouseleave&#039;, function(e) { if( idle ) { wi.resizebutton.fadeOut(); } } )&lt;br /&gt;
     .on(&#039;mousedown&#039;, function(e) {&lt;br /&gt;
       if (idle) {&lt;br /&gt;
        var lastx = e.pageX, lasty = e.pageY;&lt;br /&gt;
        wi.resizehelper.show();&lt;br /&gt;
        adjusthelper();&lt;br /&gt;
&lt;br /&gt;
        $(&#039;body&#039;)&lt;br /&gt;
         .on(&#039;mouseup.wmaresize&#039;, function(e) {&lt;br /&gt;
          $(&#039;body&#039;).off(&#039;mousemove.wmaresize&#039;);&lt;br /&gt;
          $(&#039;body&#039;).off(&#039;mouseup.wmaresize&#039;);&lt;br /&gt;
          idle = true;&lt;br /&gt;
          wi.resizehelper.hide();&lt;br /&gt;
         } )&lt;br /&gt;
         .on(&#039;mousemove.wmaresize&#039;, function(e) {&lt;br /&gt;
          wc.width -= dir*(e.pageX-lastx);&lt;br /&gt;
          wc.height += (e.pageY-lasty);&lt;br /&gt;
          lastx = e.pageX; lasty = e.pageY;&lt;br /&gt;
          wi.div.css( { width: (wc.width+2)+&#039;px&#039;, height: (wc.height+2)+&#039;px&#039; } );&lt;br /&gt;
          wi.iframe.css( { width: wc.width+&#039;px&#039;, height: wc.height+&#039;px&#039; } );&lt;br /&gt;
          adjusthelper();&lt;br /&gt;
         } );&lt;br /&gt;
&lt;br /&gt;
        idle = false;&lt;br /&gt;
       }&lt;br /&gt;
      } )&lt;br /&gt;
     .append(wi.resizebutton)&lt;br /&gt;
   );&lt;br /&gt;
  })();&lt;br /&gt;
&lt;br /&gt;
  $(window).on(&#039;message&#039;, messageHub);&lt;br /&gt;
&lt;br /&gt;
  // Fire event for other code to extend or integrate with WMA&lt;br /&gt;
  if (initPromises.length) {&lt;br /&gt;
    $.when.apply( null, initPromises ).then(function () {&lt;br /&gt;
      mw.hook(&#039;WikiMiniAtlas.load&#039;).fire();&lt;br /&gt;
    } );&lt;br /&gt;
  } else {&lt;br /&gt;
    mw.hook(&#039;WikiMiniAtlas.load&#039;).fire();&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// &amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-ProveIt&amp;diff=120483</id>
		<title>MediaWiki:Gadget-ProveIt</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-ProveIt&amp;diff=120483"/>
		<updated>2026-06-24T20:22:08Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: Protected &amp;quot;MediaWiki:Gadget-ProveIt&amp;quot; ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite)) [cascading]&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;sup&amp;gt;&amp;lt;abbr title=&amp;quot;{{int:gadgets-sister}}&amp;quot;&amp;gt;(S)&amp;lt;/abbr&amp;gt;&amp;lt;/sup&amp;gt; [[Wikipedia:ProveIt|ProveIt]] is a tool that adds a graphical user interface to find, edit, add and cite references (&amp;lt;span class=&amp;quot;plainlinks&amp;quot;&amp;gt;[{{fullurl:Fallacy|action=edit&amp;amp;withJS=MediaWiki:Gadget-ProveIt.js&amp;amp;withCSS=MediaWiki:Gadget-ProveIt.css}} demo]&amp;lt;/span&amp;gt;)&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-ProveIt&amp;diff=120482</id>
		<title>MediaWiki:Gadget-ProveIt</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-ProveIt&amp;diff=120482"/>
		<updated>2026-06-24T20:21:58Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: ←Created page with &amp;#039;&amp;lt;sup&amp;gt;&amp;lt;abbr title=&amp;quot;{{int:gadgets-sister}}&amp;quot;&amp;gt;(S)&amp;lt;/abbr&amp;gt;&amp;lt;/sup&amp;gt; ProveIt is a tool that adds a graphical user interface to find, edit, add and cite references (&amp;lt;span class=&amp;quot;plainlinks&amp;quot;&amp;gt;[{{fullurl:Fallacy|action=edit&amp;amp;withJS=MediaWiki:Gadget-ProveIt.js&amp;amp;withCSS=MediaWiki:Gadget-ProveIt.css}} demo]&amp;lt;/span&amp;gt;)&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;sup&amp;gt;&amp;lt;abbr title=&amp;quot;{{int:gadgets-sister}}&amp;quot;&amp;gt;(S)&amp;lt;/abbr&amp;gt;&amp;lt;/sup&amp;gt; [[Wikipedia:ProveIt|ProveIt]] is a tool that adds a graphical user interface to find, edit, add and cite references (&amp;lt;span class=&amp;quot;plainlinks&amp;quot;&amp;gt;[{{fullurl:Fallacy|action=edit&amp;amp;withJS=MediaWiki:Gadget-ProveIt.js&amp;amp;withCSS=MediaWiki:Gadget-ProveIt.css}} demo]&amp;lt;/span&amp;gt;)&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
	<entry>
		<id>https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-ProveIt.js&amp;diff=120481</id>
		<title>MediaWiki:Gadget-ProveIt.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.tachyony.co.uk/w/index.php?title=MediaWiki:Gadget-ProveIt.js&amp;diff=120481"/>
		<updated>2026-06-24T20:21:12Z</updated>

		<summary type="html">&lt;p&gt;Tachyony: Protected &amp;quot;MediaWiki:Gadget-ProveIt.js&amp;quot;: Highly visible template ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite)) [cascading]&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/**&lt;br /&gt;
 * ProveIt is a reference manager for Wikipedia and any other MediaWiki wiki&lt;br /&gt;
 * Documentation: https://www.mediawiki.org/wiki/ProveIt&lt;br /&gt;
 * Source code: https://www.mediawiki.org/wiki/MediaWiki:Gadget-Global-ProveIt.js&lt;br /&gt;
 */&lt;br /&gt;
function loadProveIt() {&lt;br /&gt;
	mw.config.set( {&lt;br /&gt;
&lt;br /&gt;
		// Citation templates (without namespace)&lt;br /&gt;
		&#039;proveit-templates&#039;: [&lt;br /&gt;
			&#039;Citation&#039;,&lt;br /&gt;
			&#039;Cite arXiv&#039;,&lt;br /&gt;
			&#039;Cite AV media&#039;,&lt;br /&gt;
			&#039;Cite AV media notes&#039;,&lt;br /&gt;
			&#039;Cite book&#039;,&lt;br /&gt;
			&#039;Cite bioRxiv&#039;,&lt;br /&gt;
			&#039;Cite conference&#039;,&lt;br /&gt;
			&#039;Cite comic&#039;,&lt;br /&gt;
			&#039;Cite encyclopedia&#039;,&lt;br /&gt;
			&#039;Cite episode&#039;,&lt;br /&gt;
			&#039;Cite Hansard&#039;,&lt;br /&gt;
			&#039;Cite Instagram&#039;,&lt;br /&gt;
			&#039;Cite interview&#039;,&lt;br /&gt;
			&#039;Cite journal&#039;,&lt;br /&gt;
			&#039;Cite magazine&#039;,&lt;br /&gt;
			&#039;Cite mailing list&#039;,&lt;br /&gt;
			&#039;Cite map&#039;,&lt;br /&gt;
			&#039;Cite Metacritic&#039;,&lt;br /&gt;
			&#039;Cite news&#039;,&lt;br /&gt;
			&#039;Cite newsgroup&#039;,&lt;br /&gt;
			&#039;Cite newspaper The Times&#039;,&lt;br /&gt;
			&#039;Cite ODNB&#039;,&lt;br /&gt;
			&#039;Cite paper&#039;,&lt;br /&gt;
			&#039;Cite podcast&#039;,&lt;br /&gt;
			&#039;Cite press release&#039;,&lt;br /&gt;
			&#039;Cite report&#039;,&lt;br /&gt;
			&#039;Cite Rotten Tomatoes&#039;,&lt;br /&gt;
			&#039;Cite serial&#039;,&lt;br /&gt;
			&#039;Cite sign&#039;,&lt;br /&gt;
			&#039;Cite speech&#039;,&lt;br /&gt;
			&#039;Cite techreport&#039;,&lt;br /&gt;
			&#039;Cite thesis&#039;,&lt;br /&gt;
			&#039;Cite tweet&#039;,&lt;br /&gt;
			&#039;Cite video&#039;,&lt;br /&gt;
			&#039;Cite video game&#039;,&lt;br /&gt;
			&#039;Cite ssrn&#039;,&lt;br /&gt;
			&#039;Cite wikisource&#039;,&lt;br /&gt;
			&#039;Cite web&#039;,&lt;br /&gt;
			&#039;Cite Q&#039;,&lt;br /&gt;
			&#039;R&#039;,&lt;br /&gt;
			&#039;Sfn&#039;,&lt;br /&gt;
			&#039;Sfnm&#039;&lt;br /&gt;
		],&lt;br /&gt;
&lt;br /&gt;
		// Citation templates that shouldn&#039;t go inside &amp;lt;ref&amp;gt; tags&lt;br /&gt;
		&#039;proveit-templates-noref&#039;: [ &#039;R&#039;, &#039;Sfn&#039;, &#039;Sfnm&#039; ],&lt;br /&gt;
&lt;br /&gt;
		// Preferred date format, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat#using_options&lt;br /&gt;
		&#039;proveit-date-format&#039;: { year: &#039;numeric&#039;, month: &#039;long&#039;, day: &#039;numeric&#039; },&lt;br /&gt;
&lt;br /&gt;
		// Revision tag defined at Special:Tags&lt;br /&gt;
		&#039;proveit-tag&#039;: &#039;ProveIt edit&#039;,&lt;br /&gt;
&lt;br /&gt;
		// Automatic edit summary&lt;br /&gt;
		&#039;proveit-summary&#039;: &#039;Reference edited with [[Wikipedia:ProveIt|ProveIt]]&#039;,&lt;br /&gt;
	} );&lt;br /&gt;
&lt;br /&gt;
	// Load from the central, global version at MediaWiki.org&lt;br /&gt;
	mw.loader.load( &#039;//www.mediawiki.org/w/load.php?modules=ext.gadget.Global-ProveIt&#039; );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Only load when editing&lt;br /&gt;
mw.hook( &#039;wikipage.editform&#039; ).add( () =&amp;gt; window.ProveIt || loadProveIt() );&lt;br /&gt;
mw.hook( &#039;ve.newTarget&#039; ).add( target =&amp;gt; target.constructor.static.name === &#039;article&#039; &amp;amp;&amp;amp; target.on( &#039;surfaceReady&#039;, loadProveIt ) );&lt;/div&gt;</summary>
		<author><name>Tachyony</name></author>
	</entry>
</feed>