<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="id">
	<id>http://indonesianetaudioforum.net/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Administrator</id>
	<title>Indonesia Netaudio Forum - Kontribusi pengguna [id]</title>
	<link rel="self" type="application/atom+xml" href="http://indonesianetaudioforum.net/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Administrator"/>
	<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/Istimewa:Kontribusi_pengguna/Administrator"/>
	<updated>2026-05-15T09:43:01Z</updated>
	<subtitle>Kontribusi pengguna</subtitle>
	<generator>MediaWiki 1.33.1</generator>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=MediaWiki:Sidebar&amp;diff=515</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=MediaWiki:Sidebar&amp;diff=515"/>
		<updated>2018-08-09T09:21:13Z</updated>

		<summary type="html">&lt;p&gt;Administrator: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
* navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** Indonesia Netaudio Forum | Tentang INF&lt;br /&gt;
** Category:Artikel |Artikel&lt;br /&gt;
** Category:Interview|Wawancara&lt;br /&gt;
** Category:Events|Acara&lt;br /&gt;
** Category:INF 1| INF 1&lt;br /&gt;
** Category:INF 2| INF 2&lt;br /&gt;
** Indonesia Netaudio Festival 3 | INF  3&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=MediaWiki:Gadget-HotCat/en&amp;diff=119</id>
		<title>MediaWiki:Gadget-HotCat/en</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=MediaWiki:Gadget-HotCat/en&amp;diff=119"/>
		<updated>2018-07-26T06:19:22Z</updated>

		<summary type="html">&lt;p&gt;Administrator: ←Membuat halaman berisi 'HotCat: Easily add / remove / change a category on a page, with name suggestions.'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;HotCat: Easily add / remove / change a category on a page, with name suggestions.&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=MediaWiki:Gadgets-definition&amp;diff=118</id>
		<title>MediaWiki:Gadgets-definition</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=MediaWiki:Gadgets-definition&amp;diff=118"/>
		<updated>2018-07-26T06:18:43Z</updated>

		<summary type="html">&lt;p&gt;Administrator: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Kategori ==&lt;br /&gt;
* Cat-a-lot[ResourceLoader|dependencies=mediawiki.util|type=general]|Cat-a-lot.js|Cat-a-lot.css&lt;br /&gt;
* HotCat[ResourceLoader|rights=upload|default]|HotCat.js|Hotcatcheck.js&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=MediaWiki:Gadget-Hotcatcheck.js&amp;diff=117</id>
		<title>MediaWiki:Gadget-Hotcatcheck.js</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=MediaWiki:Gadget-Hotcatcheck.js&amp;diff=117"/>
		<updated>2018-07-26T06:18:01Z</updated>

		<summary type="html">&lt;p&gt;Administrator: ←Membuat halaman berisi '/* * CheckCategories HotCat Extension – * removes the template when categorizing (prompts before) with HotCat and * adds a link &amp;quot;Categories are OK&amp;quot; to the category-s...'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/*&lt;br /&gt;
* CheckCategories HotCat Extension –&lt;br /&gt;
* removes the template when categorizing (prompts before) with HotCat and&lt;br /&gt;
* adds a link &amp;quot;Categories are OK&amp;quot; to the category-section&lt;br /&gt;
*&lt;br /&gt;
* &amp;lt;nowiki&amp;gt;&lt;br /&gt;
*&lt;br /&gt;
* @rev 2 (2014-03-20)&lt;br /&gt;
* @author [[User:Rillke]], 2012&lt;br /&gt;
* @source User:Rillke/checkCat2.js @wikimedia Commons&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/*global mw:false, $:false, alert:false */&lt;br /&gt;
/*jshint curly:false, smarttabs:true, nomen:false */&lt;br /&gt;
&lt;br /&gt;
mw.loader.using(['mediawiki.user', 'mediawiki.util', 'jquery.cookie'], function () {&lt;br /&gt;
'use strict';&lt;br /&gt;
if (6 !== mw.config.get('wgNamespaceNumber') || window.HotCatAutoRemoveCheckCatOptOut || !$('.checkcategories')[0]) return;&lt;br /&gt;
&lt;br /&gt;
var chCatRE = /\{\{[Cc]heck[ _]categories[^\}\{]*\}\}/g,&lt;br /&gt;
	selfName = '([[MediaWiki:Gadget-Hotcatcheck.js|Script]]): ',&lt;br /&gt;
	cookieName = 'checkCat',&lt;br /&gt;
	cookie = $.cookie(cookieName);&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 ** A few styling helper functions&lt;br /&gt;
 **&lt;br /&gt;
 **/&lt;br /&gt;
var createjIcon = function (iconClass) {&lt;br /&gt;
	return $('&amp;lt;span&amp;gt;')&lt;br /&gt;
		.attr('class', 'ui-icon ' + iconClass + ' catcheck-inline-icon')&lt;br /&gt;
		.text(' ');&lt;br /&gt;
};&lt;br /&gt;
var createNotifyArea = function (textNode, icon, state) {&lt;br /&gt;
	return $('&amp;lt;div&amp;gt;')&lt;br /&gt;
		.attr('class', 'ui-widget')&lt;br /&gt;
		.append(&lt;br /&gt;
			$('&amp;lt;div&amp;gt;')&lt;br /&gt;
			.attr({&lt;br /&gt;
				'class': state + ' ui-corner-all',&lt;br /&gt;
				style: 'margin-top: 20px; padding: 0.7em;'&lt;br /&gt;
			})&lt;br /&gt;
			.append(&lt;br /&gt;
				$('&amp;lt;p&amp;gt;').append(&lt;br /&gt;
				createjIcon(icon).css('marginRight', '0.3em'),&lt;br /&gt;
				textNode)));&lt;br /&gt;
};&lt;br /&gt;
mw.util.addCSS('.catcheck-inline-icon { display: inline-block; position: relative; top: 2px; }');&lt;br /&gt;
&lt;br /&gt;
// Remove &amp;quot;check categories&amp;quot; when using HotCat&lt;br /&gt;
// Only executed on first submit&lt;br /&gt;
$('body').one('submit.checkCatListener', '#hotcatCommitForm', function (e) {&lt;br /&gt;
	if ('disabled' === cookie) return true;&lt;br /&gt;
&lt;br /&gt;
	var hotCatForm = this,&lt;br /&gt;
		newVal = hotCatForm.wpTextbox1.value.replace(chCatRE, ''),&lt;br /&gt;
		dlgButtons = {},&lt;br /&gt;
		$dlgCheckCookie, $permaSaveHint, $textHintNode, $dlg;&lt;br /&gt;
&lt;br /&gt;
	var doRemove = function () {&lt;br /&gt;
		hotCatForm.wpSummary.value = 'Removing [[Template:Check categories|{' + '{Check categories}}]] ' + hotCatForm.wpSummary.value;&lt;br /&gt;
		hotCatForm.wpTextbox1.value = newVal;&lt;br /&gt;
	};&lt;br /&gt;
	var writeCookie = function (val) {&lt;br /&gt;
		$.cookie(cookieName, val, {&lt;br /&gt;
			expires: 7,&lt;br /&gt;
			path: '/'&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
	dlgButtons['Yes, Remove'] = function () {&lt;br /&gt;
		doRemove();&lt;br /&gt;
		if ($dlgCheckCookie[0].checked) writeCookie('auto');&lt;br /&gt;
		$(this).dialog('close');&lt;br /&gt;
	};&lt;br /&gt;
	dlgButtons['No, keep it'] = function () {&lt;br /&gt;
		if ($dlgCheckCookie[0].checked) writeCookie('disabled');&lt;br /&gt;
		$(this).dialog('close');&lt;br /&gt;
	};&lt;br /&gt;
	var _addToJS = function (e) {&lt;br /&gt;
		e.preventDefault();&lt;br /&gt;
		if ($permaSaveHint.hasClass('ui-state-disabled')) return;&lt;br /&gt;
&lt;br /&gt;
		var $el = $(this);&lt;br /&gt;
&lt;br /&gt;
		$el.off('click').text('Please wait.');&lt;br /&gt;
		$permaSaveHint.addClass('ui-state-disabled');&lt;br /&gt;
		var params = {&lt;br /&gt;
			action: 'edit',&lt;br /&gt;
			title: 'User:' + mw.config.get('wgUserName') + '/common.js',&lt;br /&gt;
			summary: selfName + 'Saving HotCat configuration.',&lt;br /&gt;
			appendtext: $el.data('addText'),&lt;br /&gt;
			token: (window['wikilove-edittoken'] || mw.user.tokens.get('editToken')),&lt;br /&gt;
			format: 'json'&lt;br /&gt;
		};&lt;br /&gt;
		var editDone = function (editStat) {&lt;br /&gt;
			if (!editStat) return;&lt;br /&gt;
			if (editStat.error) {&lt;br /&gt;
				alert('Unable to save to your common.js using the API\n' + editStat.error.code + '\n' + editStat.error.info);&lt;br /&gt;
				$el.text('Edit-Error!');&lt;br /&gt;
			} else {&lt;br /&gt;
				$el.text('Done.');&lt;br /&gt;
				$permaSaveHint.fadeOut();&lt;br /&gt;
			}&lt;br /&gt;
		};&lt;br /&gt;
		$.post(mw.util.wikiScript('api'), params, editDone);&lt;br /&gt;
	};&lt;br /&gt;
	/**&lt;br /&gt;
	 ** On COM:VP there were people who said:&lt;br /&gt;
	 ** &amp;quot;Categorizing with HotCat does legit automated removal of the check-cat-message&amp;quot;&lt;br /&gt;
	 ** So we invented a dialog that should be readable by users even with very few English skills.&lt;br /&gt;
	 **/&lt;br /&gt;
	var prompt = function () {&lt;br /&gt;
		$dlgCheckCookie = $('&amp;lt;input type=&amp;quot;checkbox&amp;quot; /&amp;gt;').attr({&lt;br /&gt;
			id: 'hotCatAutoRemoveCheckCatCookie'&lt;br /&gt;
		}).change(function () {&lt;br /&gt;
			if (this.checked) {&lt;br /&gt;
				$permaSaveHint.fadeIn();&lt;br /&gt;
			} else {&lt;br /&gt;
				$permaSaveHint.fadeOut();&lt;br /&gt;
			}&lt;br /&gt;
		});&lt;br /&gt;
		$textHintNode = $('&amp;lt;ul&amp;gt;');&lt;br /&gt;
		$('&amp;lt;li&amp;gt;').append($('&amp;lt;a&amp;gt;', {&lt;br /&gt;
			href: '#',&lt;br /&gt;
			text: 'Disable this feature.'&lt;br /&gt;
		}).data('addText', '\nwindow.HotCatAutoRemoveCheckCatOptOut = true;').click(_addToJS))&lt;br /&gt;
			.appendTo($textHintNode);&lt;br /&gt;
		$('&amp;lt;li&amp;gt;').append($('&amp;lt;a&amp;gt;', {&lt;br /&gt;
			href: '#',&lt;br /&gt;
			text: 'Remove {{check categories}} when editing using HotCat without prompting.'&lt;br /&gt;
		}).data('addText', '\nwindow.HotCatAutoRemoveCheckCat = true;').click(_addToJS))&lt;br /&gt;
			.appendTo($textHintNode);&lt;br /&gt;
&lt;br /&gt;
		$permaSaveHint = createNotifyArea($('&amp;lt;span&amp;gt;', {&lt;br /&gt;
			text: 'Save these setting in your common.js: '&lt;br /&gt;
		}).append($textHintNode), 'ui-icon-info', 'ui-state-highlight');&lt;br /&gt;
		$dlg = $('&amp;lt;div&amp;gt;').append($('&amp;lt;span&amp;gt;').attr({&lt;br /&gt;
			style: 'font-size: 2em; line-height: 1.8em;'&lt;br /&gt;
		}).append(&lt;br /&gt;
			$('&amp;lt;span&amp;gt;').text(&amp;quot; {{check categories}} &amp;quot;).attr({&lt;br /&gt;
			style: 'background-color:#F8CCB0; text-decoration:line-through !important; display:inline-block;'&lt;br /&gt;
		}),&lt;br /&gt;
			$('&amp;lt;span&amp;gt;').text(&amp;quot; ?&amp;quot;)))&lt;br /&gt;
			.append('&amp;lt;br&amp;gt;', $dlgCheckCookie, $('&amp;lt;label&amp;gt;').attr({&lt;br /&gt;
				'for': 'hotCatAutoRemoveCheckCatCookie'&lt;br /&gt;
			}).text('Don\'t ask again'), '&amp;lt;br&amp;gt;')&lt;br /&gt;
			.append(mw.user.isAnon() ? '' : $permaSaveHint.hide());&lt;br /&gt;
&lt;br /&gt;
		$dlg.dialog({&lt;br /&gt;
			modal: true,&lt;br /&gt;
			closeOnEscape: true,&lt;br /&gt;
			title: &amp;quot;{{check categories}} (−)?&amp;quot;,&lt;br /&gt;
			width: 450,&lt;br /&gt;
			buttons: dlgButtons,&lt;br /&gt;
			close: function () {&lt;br /&gt;
				$('#hotcatCommitForm').submit();&lt;br /&gt;
			},&lt;br /&gt;
			open: function () {&lt;br /&gt;
				var $buttons = $(this).parent().find('.ui-dialog-buttonpane button');&lt;br /&gt;
				$buttons.eq(0).button({&lt;br /&gt;
					icons: {&lt;br /&gt;
						primary: 'ui-icon-circle-check'&lt;br /&gt;
					}&lt;br /&gt;
				});&lt;br /&gt;
				$buttons.eq(1).button({&lt;br /&gt;
					icons: {&lt;br /&gt;
						primary: 'ui-icon-cancel'&lt;br /&gt;
					}&lt;br /&gt;
				});&lt;br /&gt;
			}&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
	if (newVal !== hotCatForm.wpTextbox1.value) {&lt;br /&gt;
		if (window.HotCatAutoRemoveCheckCat || cookie === 'auto') {&lt;br /&gt;
			doRemove();&lt;br /&gt;
			return true;&lt;br /&gt;
		}&lt;br /&gt;
		e.preventDefault();&lt;br /&gt;
		mw.loader.using(['jquery.ui.dialog'], function () {&lt;br /&gt;
			prompt();&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
	return true;&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// Add OK-Link to the cats panel&lt;br /&gt;
var $okLink = $('&amp;lt;a&amp;gt;', {&lt;br /&gt;
	href: '#',&lt;br /&gt;
	html: '&amp;lt;s&amp;gt;{{Check categories}}&amp;lt;/s&amp;gt;',&lt;br /&gt;
	title: 'Categories are OK! Immediately remove the template.'&lt;br /&gt;
}).click(function (e) {&lt;br /&gt;
	e.preventDefault();&lt;br /&gt;
	var $el = $(this);&lt;br /&gt;
	$el.off('click');&lt;br /&gt;
	var doEdit = function (result) {&lt;br /&gt;
		if (!result) return;&lt;br /&gt;
		$el.text('Doing.');&lt;br /&gt;
		var text = result.replace(chCatRE, '');&lt;br /&gt;
		if (text === result) {&lt;br /&gt;
			$el.text('Template not found!');&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		var params = {&lt;br /&gt;
			action: 'edit',&lt;br /&gt;
			title: mw.config.get('wgPageName'),&lt;br /&gt;
			nocreate: 1,&lt;br /&gt;
			summary: selfName + 'Categories are checked and OK. You can help [[Category:Media needing category review|reviewing]]!',&lt;br /&gt;
			text: text,&lt;br /&gt;
			token: (window['wikilove-edittoken'] || mw.user.tokens.get('csrfToken')),&lt;br /&gt;
			format: 'json'&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		var editDone = function (editStat) {&lt;br /&gt;
			if (!editStat) return;&lt;br /&gt;
			if (editStat.error) {&lt;br /&gt;
				alert('Unable to remove &amp;quot;Check categories&amp;quot; with the API\n' + editStat.error.code + '\n' + editStat.error.info);&lt;br /&gt;
				$el.text('Edit-Error!');&lt;br /&gt;
			} else {&lt;br /&gt;
				$el.text('Edit Done.');&lt;br /&gt;
			}&lt;br /&gt;
			$('.checkcategories').fadeOut();&lt;br /&gt;
		};&lt;br /&gt;
		$el.text('Doing..');&lt;br /&gt;
		$.post(mw.util.wikiScript('api'), params, editDone);&lt;br /&gt;
	};&lt;br /&gt;
	$el.text('Doing');&lt;br /&gt;
	$.ajax({&lt;br /&gt;
		url: mw.config.get('wgScript'),&lt;br /&gt;
		data: {&lt;br /&gt;
			action: 'raw',&lt;br /&gt;
			title: mw.config.get('wgPageName').replace(/ /g, '_'),&lt;br /&gt;
			maxage: 0,&lt;br /&gt;
			smaxage: 0&lt;br /&gt;
		},&lt;br /&gt;
		dataType: 'text',&lt;br /&gt;
		error: function () {&lt;br /&gt;
			$el.text('Error!');&lt;br /&gt;
		},&lt;br /&gt;
		success: doEdit,&lt;br /&gt;
		type: 'GET',&lt;br /&gt;
		cache: false&lt;br /&gt;
	});&lt;br /&gt;
});&lt;br /&gt;
$(function () {&lt;br /&gt;
	$('#catlinks').find('ul:first').append($('&amp;lt;li&amp;gt;').append($okLink));&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
});&lt;br /&gt;
//&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=MediaWiki:Gadget-HotCat.js&amp;diff=116</id>
		<title>MediaWiki:Gadget-HotCat.js</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=MediaWiki:Gadget-HotCat.js&amp;diff=116"/>
		<updated>2018-07-26T06:17:33Z</updated>

		<summary type="html">&lt;p&gt;Administrator: ←Membuat halaman berisi '/** HotCat V2.39  Ajax-based simple Category manager. Allows adding/removing/changing categories on a page view. Supports multiple category changes, as well as redirec...'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/**&lt;br /&gt;
HotCat V2.39&lt;br /&gt;
&lt;br /&gt;
Ajax-based simple Category manager. Allows adding/removing/changing categories on a page view.&lt;br /&gt;
Supports multiple category changes, as well as redirect and disambiguation resolution. Also&lt;br /&gt;
plugs into the upload form. Search engines to use for the suggestion list are configurable, and&lt;br /&gt;
can be selected interactively.&lt;br /&gt;
&lt;br /&gt;
Documentation: https://commons.wikimedia.org/wiki/Help:Gadget-HotCat&lt;br /&gt;
List of main authors: https://commons.wikimedia.org/wiki/Help:Gadget-HotCat/Version_history&lt;br /&gt;
&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;
This code should run on any MediaWiki installation &amp;gt;= MW 1.27.&lt;br /&gt;
&lt;br /&gt;
For use with older versions of MediaWiki, use the archived versions below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;=1.26: https://commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-HotCat.js&amp;amp;oldid=211134664&lt;br /&gt;
*/&lt;br /&gt;
// &amp;lt;nowiki&amp;gt;&lt;br /&gt;
/* eslint-disable vars-on-top, one-var, camelcase, no-alert, curly */&lt;br /&gt;
/* global jQuery, mediaWiki, UFUI, JSconfig, UploadForm */&lt;br /&gt;
/* jslint strict:false, nonew:false, bitwise:true */&lt;br /&gt;
( function ( $, mw ) {&lt;br /&gt;
	// Don't use mw.config.get() as that takes a copy of the config, and so doesn't&lt;br /&gt;
	// account for values changing, e.g. wgCurRevisionId after a VE edit&lt;br /&gt;
	var conf = mw.config.values;&lt;br /&gt;
&lt;br /&gt;
	// Guard against double inclusions (in old IE/Opera element ids become window properties)&lt;br /&gt;
	if ( ( window.HotCat &amp;amp;&amp;amp; !window.HotCat.nodeName ) ||&lt;br /&gt;
		conf.wgAction === 'edit' ) // Not on edit mode&lt;br /&gt;
		return;&lt;br /&gt;
&lt;br /&gt;
	// Configuration stuff.&lt;br /&gt;
	var HC = window.HotCat = {&lt;br /&gt;
		// Localize these messages to the main language of your wiki.&lt;br /&gt;
		messages: {&lt;br /&gt;
			cat_removed: 'removed [[Category:$1]]',&lt;br /&gt;
			template_removed: 'removed {{[[Category:$1]]}}',&lt;br /&gt;
			cat_added: 'added [[Category:$1]]',&lt;br /&gt;
			cat_keychange: 'new key for [[Category:$1]]: &amp;quot;$2&amp;quot;', // $2 is the new key&lt;br /&gt;
			cat_notFound: 'Category &amp;quot;$1&amp;quot; not found',&lt;br /&gt;
			cat_exists: 'Category &amp;quot;$1&amp;quot; already exists; not added.',&lt;br /&gt;
			cat_resolved: ' (redirect [[Category:$1]] resolved)',&lt;br /&gt;
			uncat_removed: 'removed {{uncategorized}}',&lt;br /&gt;
			separator: '; ',&lt;br /&gt;
			// Some text to prefix to the edit summary.&lt;br /&gt;
			prefix: '',&lt;br /&gt;
			// Some text to append to the edit summary. Named 'using' for historical reasons. If you prefer&lt;br /&gt;
			// to have a marker at the front, use prefix and set this to the empty string.&lt;br /&gt;
			using: ' using [[Help:Gadget-HotCat|HotCat]]',&lt;br /&gt;
			// $1 is replaced by a number. If your language has several plural forms (c.f. [[:en:Dual (grammatical form)]]),&lt;br /&gt;
			// you can set this to an array of strings suitable for passing to mw.language.configPlural().&lt;br /&gt;
			// If that function doesn't exist, HotCat will simply fall back to using the last&lt;br /&gt;
			// entry in the array.&lt;br /&gt;
			multi_change: '$1 categories',&lt;br /&gt;
			// Button text. Localize to wgContentLanguage here; localize to wgUserLanguage in a subpage,&lt;br /&gt;
			// see localization hook below.&lt;br /&gt;
			commit: 'Save',&lt;br /&gt;
			// Button text. Localize to wgContentLanguage here; localize to wgUserLanguage in a subpage,&lt;br /&gt;
			// see localization hook below.&lt;br /&gt;
			ok: 'OK',&lt;br /&gt;
			// Button text. Localize to wgContentLanguage here; localize to wgUserLanguage in a subpage,&lt;br /&gt;
			// see localization hook below.&lt;br /&gt;
			cancel: 'Cancel',&lt;br /&gt;
			// Localize to wgContentLanguage here; localize to wgUserLanguage in a subpage,&lt;br /&gt;
			// see localization hook below.&lt;br /&gt;
			multi_error: 'Could not retrieve the page text from the server. Therefore, your category changes ' +&lt;br /&gt;
			'cannot be saved. We apologize for the inconvenience.',&lt;br /&gt;
			// Defaults to '[[' + category_canonical + ':$1]]'. Can be overridden if in the short edit summaries&lt;br /&gt;
			// not the standard category name should be used but, say, a shorter namespace alias. $1 is replaced&lt;br /&gt;
			// by a category name.&lt;br /&gt;
			short_catchange: null&lt;br /&gt;
		},&lt;br /&gt;
		// Plural of category_canonical.&lt;br /&gt;
		categories: 'Categories',&lt;br /&gt;
		// Any category in this category is deemed a disambiguation category; i.e., a category that should not contain&lt;br /&gt;
		// any items, but that contains links to other categories where stuff should be categorized. If you don't have&lt;br /&gt;
		// that concept on your wiki, set it to null. Use blanks, not underscores.&lt;br /&gt;
		disambig_category: 'Disambiguation',&lt;br /&gt;
		// Any category in this category is deemed a (soft) redirect to some other category defined by a link&lt;br /&gt;
		// to another non-blacklisted category. If your wiki doesn't have soft category redirects, set this to null.&lt;br /&gt;
		// If a soft-redirected category contains more than one link to another non-blacklisted category, it's considered&lt;br /&gt;
		// a disambiguation category instead.&lt;br /&gt;
		redir_category: 'Category redirects',&lt;br /&gt;
		// The little modification links displayed after category names. U+2212 is a minus sign; U+2193 and U+2191 are&lt;br /&gt;
		// downward and upward pointing arrows. Do not use ↓ and ↑ in the code!&lt;br /&gt;
		links: {&lt;br /&gt;
			change: '(±)',&lt;br /&gt;
			remove: '(\u2212)',&lt;br /&gt;
			add: '(+)',&lt;br /&gt;
			restore: '(×)',&lt;br /&gt;
			undo: '(×)',&lt;br /&gt;
			down: '(\u2193)',&lt;br /&gt;
			up: '(\u2191)'&lt;br /&gt;
		},&lt;br /&gt;
		changeTag: conf.wgUserName ? 'HotCat' : '', // if tag is missing, edit is rejected&lt;br /&gt;
		// The tooltips for the above links&lt;br /&gt;
		tooltips: {&lt;br /&gt;
			change: 'Modify',&lt;br /&gt;
			remove: 'Remove',&lt;br /&gt;
			add: 'Add a new category',&lt;br /&gt;
			restore: 'Undo changes',&lt;br /&gt;
			undo: 'Undo changes',&lt;br /&gt;
			down: 'Open for modifying and display subcategories',&lt;br /&gt;
			up: 'Open for modifying and display parent categories'&lt;br /&gt;
		},&lt;br /&gt;
		// The HTML content of the &amp;quot;enter multi-mode&amp;quot; link at the front.&lt;br /&gt;
		addmulti: '&amp;lt;span&amp;gt;+&amp;lt;sup&amp;gt;+&amp;lt;/sup&amp;gt;&amp;lt;/span&amp;gt;',&lt;br /&gt;
		// Tooltip for the &amp;quot;enter multi-mode&amp;quot; link&lt;br /&gt;
		multi_tooltip: 'Modify several categories',&lt;br /&gt;
		// Return true to disable HotCat.&lt;br /&gt;
		disable: function () {&lt;br /&gt;
			var ns = conf.wgNamespaceNumber;&lt;br /&gt;
			var nsIds = conf.wgNamespaceIds;&lt;br /&gt;
			return (&lt;br /&gt;
				ns &amp;lt; 0 || // Special pages; Special:Upload is handled differently&lt;br /&gt;
			ns === 10 || // Templates&lt;br /&gt;
			ns === 828 || // Module (Lua)&lt;br /&gt;
			ns === 8 || // MediaWiki&lt;br /&gt;
			ns === 6 &amp;amp;&amp;amp; !conf.wgArticleId || // Non-existing file pages&lt;br /&gt;
			ns === 2 &amp;amp;&amp;amp; /\.(js|css)$/.test( conf.wgTitle ) || // User scripts&lt;br /&gt;
			nsIds &amp;amp;&amp;amp;&lt;br /&gt;
			( ns === nsIds.creator ||&lt;br /&gt;
			ns === nsIds.timedtext ||&lt;br /&gt;
			ns === nsIds.institution ) );&lt;br /&gt;
		},&lt;br /&gt;
		// A regexp matching a templates used to mark uncategorized pages, if your wiki does have that.&lt;br /&gt;
		// If not, set it to null.&lt;br /&gt;
		uncat_regexp: /\{\{\s*[Uu]ncategorized\s*[^}]*\}\}\s*(&amp;lt;!--.*?--&amp;gt;\s*)?/g,&lt;br /&gt;
		// The images used for the little indication icon. Should not need changing.&lt;br /&gt;
		existsYes: '//upload.wikimedia.org/wikipedia/commons/thumb/b/be/P_yes.svg/20px-P_yes.svg.png',&lt;br /&gt;
		existsNo: '//upload.wikimedia.org/wikipedia/commons/thumb/4/42/P_no.svg/20px-P_no.svg.png',&lt;br /&gt;
		// a list of categories which can be removed by removing a template&lt;br /&gt;
		// key: the category without namespace&lt;br /&gt;
		// value: A regexp matching the template name, again without namespace&lt;br /&gt;
		// If you don't have this at your wiki, or don't want this, set it to an empty object {}.&lt;br /&gt;
		template_categories: {},&lt;br /&gt;
		// Names for the search engines&lt;br /&gt;
		engine_names: {&lt;br /&gt;
			searchindex: 'Search index',&lt;br /&gt;
			pagelist: 'Page list',&lt;br /&gt;
			combined: 'Combined search',&lt;br /&gt;
			subcat: 'Subcategories',&lt;br /&gt;
			parentcat: 'Parent categories'&lt;br /&gt;
		},&lt;br /&gt;
		// Set to false if your wiki has case-sensitive page names. MediaWiki has two modes: either the 		// any items, but that contains links to other categories where stuff should be categorized. If you don't have&lt;br /&gt;
&lt;br /&gt;
		// (&amp;quot;case-sensitive&amp;quot;; Category:aa !== Category:Aa). It doesn't currently have a fully case-insensitive mode&lt;br /&gt;
		// (which would mean Category:aa === Category:Aa === Category:AA === Category:aA)&lt;br /&gt;
		// HotCat tries to set this correctly automatically using an API query. It's still a good idea to manually&lt;br /&gt;
		// configure it correctly; either directly here if you copied HotCat, or in the local configuration file&lt;br /&gt;
		// MediaWiki:Gadget-HotCat.js/local_defaults if you hotlink to the Commons-version, to ensure it is set even&lt;br /&gt;
		// if that API query should fail for some strange reason.&lt;br /&gt;
		capitalizePageNames: true,&lt;br /&gt;
		// If upload_disabled is true, HotCat will not be used on the Upload form.&lt;br /&gt;
		upload_disabled: false,&lt;br /&gt;
		// Single regular expression matching blacklisted categories that cannot be changed or&lt;br /&gt;
		// added using HotCat. For instance /\bstubs?$/ (any category ending with the word &amp;quot;stub&amp;quot;&lt;br /&gt;
		// or &amp;quot;stubs&amp;quot;), or /(\bstubs?$)|\bmaintenance\b/ (stub categories and any category with the&lt;br /&gt;
		// word &amp;quot;maintenance&amp;quot; in its title.&lt;br /&gt;
		blacklist: null,&lt;br /&gt;
&lt;br /&gt;
		// Stuff changeable by users:&lt;br /&gt;
		// Background for changed categories in multi-edit mode. Default is a very light salmon pink.&lt;br /&gt;
		bg_changed: '#FCA',&lt;br /&gt;
		// If true, HotCat will never automatically submit changes. HotCat will only open an edit page with&lt;br /&gt;
		// the changes; users must always save explicitly.&lt;br /&gt;
		no_autocommit: false,&lt;br /&gt;
		// If true, the &amp;quot;category deletion&amp;quot; link &amp;quot;(-)&amp;quot; will never save automatically but always show an&lt;br /&gt;
		// edit page where the user has to save the edit manually. Is false by default because that's the&lt;br /&gt;
		// traditional behavior. This setting overrides no_autocommit for &amp;quot;(-)&amp;quot; links.&lt;br /&gt;
		del_needs_diff: false,&lt;br /&gt;
		// Time, in milliseconds, that HotCat waits after a keystroke before making a request to the&lt;br /&gt;
		// server to get suggestions.&lt;br /&gt;
		suggest_delay: 100,&lt;br /&gt;
		// Default width, in characters, of the text input field.&lt;br /&gt;
		editbox_width: 40,&lt;br /&gt;
		// One of the engine_names above, to be used as the default suggestion engine.&lt;br /&gt;
		suggestions: 'combined',&lt;br /&gt;
		// If true, always use the default engine, and never display a selector.&lt;br /&gt;
		fixed_search: false,&lt;br /&gt;
		// If false, do not display the &amp;quot;up&amp;quot; and &amp;quot;down&amp;quot; links&lt;br /&gt;
		use_up_down: true,&lt;br /&gt;
		// Default list size&lt;br /&gt;
		listSize: 5,&lt;br /&gt;
		// If true, single category changes are marked as minor edits. If false, they're not.&lt;br /&gt;
		single_minor: true,&lt;br /&gt;
		// If true, never add a page to the user's watchlist. If false, pages get added to the watchlist if&lt;br /&gt;
		// the user has the &amp;quot;Add pages I edit to my watchlist&amp;quot; or the &amp;quot;Add pages I create to my watchlist&amp;quot;&lt;br /&gt;
		// options in his or her preferences set.&lt;br /&gt;
		dont_add_to_watchlist: false,&lt;br /&gt;
		shortcuts: null,&lt;br /&gt;
		addShortcuts: function ( map ) {&lt;br /&gt;
			if ( !map ) return;&lt;br /&gt;
			window.HotCat.shortcuts = window.HotCat.shortcuts || {};&lt;br /&gt;
			for ( var k in map ) {&lt;br /&gt;
				if ( !map.hasOwnProperty( k ) || typeof k !== 'string' ) continue;&lt;br /&gt;
&lt;br /&gt;
				var v = map[ k ];&lt;br /&gt;
				if ( typeof v !== 'string' ) continue;&lt;br /&gt;
&lt;br /&gt;
				k = k.replace( /^\s+|\s+$/g, '' );&lt;br /&gt;
				v = v.replace( /^\s+|\s+$/g, '' );&lt;br /&gt;
				if ( !k.length || !v.length ) continue;&lt;br /&gt;
&lt;br /&gt;
				window.HotCat.shortcuts[ k ] = v;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	// More backwards compatibility. We have a few places where we test for the browser: once for&lt;br /&gt;
	// Safari &amp;lt; 3.0, and twice for WebKit (Chrome or Safari, any versions)&lt;br /&gt;
	var ua = navigator.userAgent.toLowerCase();&lt;br /&gt;
	var is_webkit = /applewebkit\/\d+/.test( ua ) &amp;amp;&amp;amp; ua.indexOf( 'spoofer' ) &amp;lt; 0;&lt;br /&gt;
	var cat_prefix = null;&lt;br /&gt;
	var noSuggestions = false;&lt;br /&gt;
&lt;br /&gt;
	function armorUri( uri ) {&lt;br /&gt;
	// Avoid protocol-relative URIs, IE7 has a bug with them in Ajax calls&lt;br /&gt;
		if ( uri.length &amp;gt;= 2 &amp;amp;&amp;amp; uri.substring( 0, 2 ) === '//' ) return document.location.protocol + uri;&lt;br /&gt;
&lt;br /&gt;
		return uri;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function LoadTrigger( needed ) {&lt;br /&gt;
		this.queue = [];&lt;br /&gt;
		this.toLoad = needed;&lt;br /&gt;
	}&lt;br /&gt;
	LoadTrigger.prototype = {&lt;br /&gt;
		register: function ( callback ) {&lt;br /&gt;
			if ( this.toLoad &amp;lt;= 0 ) callback(); // Execute directly&lt;br /&gt;
			else this.queue[ this.queue.length ] = callback;&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		loaded: function () {&lt;br /&gt;
			if ( this.toLoad &amp;gt; 0 ) {&lt;br /&gt;
				this.toLoad--;&lt;br /&gt;
				if ( this.toLoad === 0 ) {&lt;br /&gt;
				// Run queued callbacks once&lt;br /&gt;
					for ( var i = 0; i &amp;lt; this.queue.length; i++ ) this.queue[ i ]();&lt;br /&gt;
&lt;br /&gt;
					this.queue = [];&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	var setupCompleted = new LoadTrigger( 1 );&lt;br /&gt;
	// Used to run user-registered code once HotCat is fully set up and ready.&lt;br /&gt;
	HC.runWhenReady = function ( callback ) {&lt;br /&gt;
		setupCompleted.register( callback );&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	var loadTrigger = new LoadTrigger( 2 );&lt;br /&gt;
	// Used to delay running the HotCat setup until /local_defaults and localizations have been loaded.&lt;br /&gt;
&lt;br /&gt;
	function load( uri ) {&lt;br /&gt;
		var head = document.getElementsByTagName( 'head' )[ 0 ];&lt;br /&gt;
		var s = document.createElement( 'script' );&lt;br /&gt;
		s.setAttribute( 'src', armorUri( uri ) );&lt;br /&gt;
		s.setAttribute( 'type', 'text/javascript' );&lt;br /&gt;
		var done = false;&lt;br /&gt;
&lt;br /&gt;
		function afterLoad() {&lt;br /&gt;
			if ( done ) return;&lt;br /&gt;
			done = true;&lt;br /&gt;
			s.onload = s.onreadystatechange = s.onerror = null; // Properly clean up to avoid memory leaks in IE&lt;br /&gt;
			if ( head &amp;amp;&amp;amp; s.parentNode ) head.removeChild( s );&lt;br /&gt;
&lt;br /&gt;
			loadTrigger.loaded();&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		s.onload = s.onreadystatechange = function () { // onreadystatechange for IE, onload for all others&lt;br /&gt;
			if ( done ) return;&lt;br /&gt;
			if ( !this.readyState || this.readyState === 'loaded' || this.readyState === 'complete' ) afterLoad();&lt;br /&gt;
		};&lt;br /&gt;
		s.onerror = afterLoad; // Clean up, but otherwise ignore errors&lt;br /&gt;
		head.insertBefore( s, head.firstChild ); // appendChild may trigger bugs in IE6 here&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function loadJS( page ) {&lt;br /&gt;
		load( conf.wgServer + conf.wgScript + '?title=' + encodeURIComponent( page ) + '&amp;amp;action=raw&amp;amp;ctype=text/javascript' );&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function loadURI( href ) {&lt;br /&gt;
		var url = href;&lt;br /&gt;
		if ( url.substring( 0, 2 ) === '//' ) url = window.location.protocol + url; else if ( url.substring( 0, 1 ) === '/' ) url = conf.wgServer + url;&lt;br /&gt;
&lt;br /&gt;
		load( url );&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Load local configurations, overriding the pre-set default values in the HotCat object above. This is always loaded&lt;br /&gt;
	// from the wiki where this script is executing, even if this script itself is hotlinked from the Commons. This can&lt;br /&gt;
	// be used to change the default settings, or to provide localized interface texts for edit summaries and so on.&lt;br /&gt;
	loadJS( 'MediaWiki:Gadget-HotCat.js/local_defaults' );&lt;br /&gt;
&lt;br /&gt;
	// Load localized UI texts. These are the texts that HotCat displays on the page itself. Texts shown in edit summaries&lt;br /&gt;
	// should be localized in /local_defaults above.&lt;br /&gt;
	if ( conf.wgUserLanguage !== 'en' ) {&lt;br /&gt;
		// Lupo: somebody thought it would be a good idea to add this. So the default is true, and you have to set it to false&lt;br /&gt;
		// explicitly if you're not on the Commons and don't want that.&lt;br /&gt;
		if ( window.hotcat_translations_from_commons === undefined ) window.hotcat_translations_from_commons = true;&lt;br /&gt;
&lt;br /&gt;
		// Localization hook to localize HotCat messages, tooltips, and engine names for wgUserLanguage.&lt;br /&gt;
		if ( window.hotcat_translations_from_commons &amp;amp;&amp;amp; conf.wgServer.indexOf( '//commons' ) &amp;lt; 0 ) {&lt;br /&gt;
			loadURI( '//commons.wikimedia.org/w/index.php?title=' +&lt;br /&gt;
		'MediaWiki:Gadget-HotCat.js/' + conf.wgUserLanguage +&lt;br /&gt;
		'&amp;amp;action=raw&amp;amp;ctype=text/javascript' );&lt;br /&gt;
		} else {&lt;br /&gt;
		// Load translations locally&lt;br /&gt;
			loadJS( 'MediaWiki:Gadget-HotCat.js/' + conf.wgUserLanguage );&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		loadTrigger.loaded();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// No further changes should be necessary here.&lt;br /&gt;
&lt;br /&gt;
	// The following regular expression strings are used when searching for categories in wikitext.&lt;br /&gt;
	var wikiTextBlank = '[\\t _\\xA0\\u1680\\u180E\\u2000-\\u200A\\u2028\\u2029\\u202F\\u205F\\u3000]+';&lt;br /&gt;
	var wikiTextBlankRE = new RegExp( wikiTextBlank, 'g' );&lt;br /&gt;
	// Regexp for handling blanks inside a category title or namespace name.&lt;br /&gt;
	// See http://svn.wikimedia.org/viewvc/mediawiki/trunk/phase3/includes/Title.php?revision=104051&amp;amp;view=markup#l2722&lt;br /&gt;
	// See also http://www.fileformat.info/info/unicode/category/Zs/list.htm&lt;br /&gt;
	//   MediaWiki collapses several contiguous blanks inside a page title to one single blank. It also replace a&lt;br /&gt;
	// number of special whitespace characters by simple blanks. And finally, blanks are treated as underscores.&lt;br /&gt;
	// Therefore, when looking for page titles in wikitext, we must handle all these cases.&lt;br /&gt;
	//   Note: we _do_ include the horizontal tab in the above list, even though the MediaWiki software for some reason&lt;br /&gt;
	// appears to not handle it. The zero-width space \u200B is _not_ handled as a space inside titles by MW.&lt;br /&gt;
	var wikiTextBlankOrBidi = '[\\t _\\xA0\\u1680\\u180E\\u2000-\\u200B\\u200E\\u200F\\u2028-\\u202F\\u205F\\u3000]*';&lt;br /&gt;
	// Whitespace regexp for handling whitespace between link components. Including the horizontal tab, but not \n\r\f\v:&lt;br /&gt;
	// a link must be on one single line.&lt;br /&gt;
	//   MediaWiki also removes Unicode bidi override characters in page titles (and namespace names) completely.&lt;br /&gt;
	// This is *not* handled, as it would require us to allow any of [\u200E\u200F\u202A-\u202E] between any two&lt;br /&gt;
	// characters inside a category link. It _could_ be done though... We _do_ handle strange spaces, including the&lt;br /&gt;
	// zero-width space \u200B, and bidi overrides between the components of a category link (adjacent to the colon,&lt;br /&gt;
	// or adjacent to and inside of &amp;quot;[[&amp;quot; and &amp;quot;]]&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
	// First auto-localize the regexps for the category and the template namespaces.&lt;br /&gt;
	var formattedNamespaces = conf.wgFormattedNamespaces;&lt;br /&gt;
	var namespaceIds = conf.wgNamespaceIds;&lt;br /&gt;
	function autoLocalize( namespaceNumber, fallback ) {&lt;br /&gt;
		function createRegexpStr( name ) {&lt;br /&gt;
			if ( !name || !name.length ) return '';&lt;br /&gt;
&lt;br /&gt;
			var regex_name = '';&lt;br /&gt;
			for ( var i = 0; i &amp;lt; name.length; i++ ) {&lt;br /&gt;
				var initial = name.charAt( i ),&lt;br /&gt;
					ll = initial.toLowerCase(),&lt;br /&gt;
					ul = initial.toUpperCase();&lt;br /&gt;
				if ( ll === ul ) regex_name += initial; else regex_name += '[' + ll + ul + ']';&lt;br /&gt;
			}&lt;br /&gt;
			return regex_name&lt;br /&gt;
				.replace( /([\\^$.?*+()])/g, '\\$1' )&lt;br /&gt;
				.replace( wikiTextBlankRE, wikiTextBlank );&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		fallback = fallback.toLowerCase();&lt;br /&gt;
		var canonical = formattedNamespaces[ String( namespaceNumber ) ].toLowerCase();&lt;br /&gt;
		var regexp = createRegexpStr( canonical );&lt;br /&gt;
		if ( fallback &amp;amp;&amp;amp; canonical !== fallback ) regexp += '|' + createRegexpStr( fallback );&lt;br /&gt;
&lt;br /&gt;
		if ( namespaceIds ) {&lt;br /&gt;
			for ( var cat_name in namespaceIds ) {&lt;br /&gt;
				if (&lt;br /&gt;
					typeof cat_name === 'string' &amp;amp;&amp;amp;&lt;br /&gt;
					cat_name.toLowerCase() !== canonical &amp;amp;&amp;amp;&lt;br /&gt;
					cat_name.toLowerCase() !== fallback &amp;amp;&amp;amp;&lt;br /&gt;
					namespaceIds[ cat_name ] === namespaceNumber&lt;br /&gt;
				) {&lt;br /&gt;
					regexp += '|' + createRegexpStr( cat_name );&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return regexp;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	HC.category_canonical = formattedNamespaces[ '14' ];&lt;br /&gt;
	HC.category_regexp = autoLocalize( 14, 'category' );&lt;br /&gt;
	if ( formattedNamespaces[ '10' ] ) HC.template_regexp = autoLocalize( 10, 'template' );&lt;br /&gt;
&lt;br /&gt;
	// Utility functions. Yes, this duplicates some functionality that also exists in other places, but&lt;br /&gt;
	// to keep this whole stuff in a single file not depending on any other on-wiki JavaScripts, we re-do&lt;br /&gt;
	// these few operations here.&lt;br /&gt;
	function make( arg, literal ) {&lt;br /&gt;
		if ( !arg ) return null;&lt;br /&gt;
&lt;br /&gt;
		return literal ? document.createTextNode( arg ) : document.createElement( arg );&lt;br /&gt;
	}&lt;br /&gt;
	function param( name, uri ) {&lt;br /&gt;
		uri = uri || document.location.href;&lt;br /&gt;
		var re = new RegExp( '[&amp;amp;?]' + name + '=([^&amp;amp;#]*)' );&lt;br /&gt;
		var m = re.exec( uri );&lt;br /&gt;
		if ( m &amp;amp;&amp;amp; m.length &amp;gt; 1 ) return decodeURIComponent( m[ 1 ] );&lt;br /&gt;
		return null;&lt;br /&gt;
	}&lt;br /&gt;
	function title( href ) {&lt;br /&gt;
		if ( !href ) return null;&lt;br /&gt;
&lt;br /&gt;
		var script = conf.wgScript + '?';&lt;br /&gt;
		if ( href.indexOf( script ) === 0 || href.indexOf( conf.wgServer + script ) === 0 || conf.wgServer.substring( 0, 2 ) === '//' &amp;amp;&amp;amp; href.indexOf( document.location.protocol + conf.wgServer + script ) === 0 ) {&lt;br /&gt;
			// href=&amp;quot;/w/index.php?title=...&amp;quot;&lt;br /&gt;
			return param( 'title', href );&lt;br /&gt;
		} else {&lt;br /&gt;
			// href=&amp;quot;/wiki/...&amp;quot;&lt;br /&gt;
			var prefix = conf.wgArticlePath.replace( '$1', '' );&lt;br /&gt;
			if ( href.indexOf( prefix ) ) prefix = conf.wgServer + prefix; // Fully expanded URL?&lt;br /&gt;
&lt;br /&gt;
			if ( href.indexOf( prefix ) &amp;amp;&amp;amp; prefix.substring( 0, 2 ) === '//' ) prefix = document.location.protocol + prefix; // Protocol-relative wgServer?&lt;br /&gt;
&lt;br /&gt;
			if ( href.indexOf( prefix ) === 0 ) return decodeURIComponent( href.substring( prefix.length ) );&lt;br /&gt;
		}&lt;br /&gt;
		return null;&lt;br /&gt;
	}&lt;br /&gt;
	function hasClass( elem, name ) {&lt;br /&gt;
		return ( ' ' + elem.className + ' ' ).indexOf( ' ' + name + ' ' ) &amp;gt;= 0;&lt;br /&gt;
	}&lt;br /&gt;
	function capitalize( str ) {&lt;br /&gt;
		if ( !str || !str.length ) return str;&lt;br /&gt;
&lt;br /&gt;
		return str.substr( 0, 1 ).toUpperCase() + str.substr( 1 );&lt;br /&gt;
	}&lt;br /&gt;
	function wikiPagePath( pageName ) {&lt;br /&gt;
		// Note: do not simply use encodeURI, it doesn't encode '&amp;amp;', which might break if wgArticlePath actually has the $1 in&lt;br /&gt;
		// a query parameter.&lt;br /&gt;
		return conf.wgArticlePath.replace( '$1', encodeURIComponent( pageName ).replace( /%3A/g, ':' ).replace( /%2F/g, '/' ) );&lt;br /&gt;
	}&lt;br /&gt;
	function escapeRE( str ) {&lt;br /&gt;
		return str.replace( /([\\^$.?*+()[\]])/g, '\\$1' );&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function substituteFactory( options ) {&lt;br /&gt;
		options = options || {};&lt;br /&gt;
		var lead = options.indicator || '$';&lt;br /&gt;
		var indicator = escapeRE( lead );&lt;br /&gt;
		var lbrace = escapeRE( options.lbrace || '{' );&lt;br /&gt;
		var rbrace = escapeRE( options.rbrace || '}' );&lt;br /&gt;
		var re;&lt;br /&gt;
&lt;br /&gt;
		re = new RegExp(&lt;br /&gt;
			// $$&lt;br /&gt;
			'(?:' + indicator + '(' + indicator + '))|' +&lt;br /&gt;
			// $0, $1&lt;br /&gt;
			'(?:' + indicator + '(\\d+))|' +&lt;br /&gt;
			// ${key}&lt;br /&gt;
			'(?:' + indicator + '(?:' + lbrace + '([^' + lbrace + rbrace + ']+)' + rbrace + '))|' +&lt;br /&gt;
			// $key (only if first char after $ is not $, digit, or { )&lt;br /&gt;
			'(?:' + indicator + '(?!(?:[' + indicator + lbrace + ']|\\d))(\\S+?)\\b)',&lt;br /&gt;
			'g'&lt;br /&gt;
		);&lt;br /&gt;
		// Replace $1, $2, or ${key1}, ${key2}, or $key1, $key2 by values from map. $$ is replaced by a single $.&lt;br /&gt;
		return function ( str, map ) {&lt;br /&gt;
			if ( !map ) return str;&lt;br /&gt;
&lt;br /&gt;
			return str.replace( re, function ( match, prefix, idx, key, alpha ) {&lt;br /&gt;
				if ( prefix === lead ) return lead;&lt;br /&gt;
&lt;br /&gt;
				var k = alpha || key || idx;&lt;br /&gt;
				var replacement = typeof map[ k ] === 'function' ? map[ k ]( match, k ) : map[ k ];&lt;br /&gt;
				return typeof replacement === 'string' ? replacement : ( replacement || match );&lt;br /&gt;
			} );&lt;br /&gt;
		};&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var substitute = substituteFactory();&lt;br /&gt;
	var replaceShortcuts = ( function () {&lt;br /&gt;
		var replaceHash = substituteFactory( {&lt;br /&gt;
			indicator: '#',&lt;br /&gt;
			lbrace: '[',&lt;br /&gt;
			rbrace: ']'&lt;br /&gt;
		} );&lt;br /&gt;
		return function ( str, map ) {&lt;br /&gt;
			var s = replaceHash( str, map );&lt;br /&gt;
			return HC.capitalizePageNames ? capitalize( s ) : s;&lt;br /&gt;
		};&lt;br /&gt;
	}() );&lt;br /&gt;
&lt;br /&gt;
	// Text modification&lt;br /&gt;
&lt;br /&gt;
	var findCatsRE =&lt;br /&gt;
	new RegExp( '\\[\\[' + wikiTextBlankOrBidi + '(?:' + HC.category_regexp + ')' + wikiTextBlankOrBidi + ':[^\\]]+\\]\\]', 'g' );&lt;br /&gt;
&lt;br /&gt;
	function replaceByBlanks( match ) {&lt;br /&gt;
		return match.replace( /(\s|\S)/g, ' ' ); // /./ doesn't match linebreaks. /(\s|\S)/ does.&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function find_category( wikitext, category, once ) {&lt;br /&gt;
		var cat_regex = null;&lt;br /&gt;
		if ( HC.template_categories[ category ] ) {&lt;br /&gt;
			cat_regex = new RegExp(&lt;br /&gt;
				'\\{\\{' + wikiTextBlankOrBidi + '(' + HC.template_regexp + '(?=' + wikiTextBlankOrBidi + ':))?' + wikiTextBlankOrBidi +&lt;br /&gt;
				'(?:' + HC.template_categories[ category ] + ')' +&lt;br /&gt;
				wikiTextBlankOrBidi + '(\\|.*?)?\\}\\}',&lt;br /&gt;
				'g'&lt;br /&gt;
			);&lt;br /&gt;
		} else {&lt;br /&gt;
			var cat_name = escapeRE( category );&lt;br /&gt;
			var initial = cat_name.substr( 0, 1 );&lt;br /&gt;
			cat_regex = new RegExp(&lt;br /&gt;
				'\\[\\[' + wikiTextBlankOrBidi + '(' + HC.category_regexp + ')' + wikiTextBlankOrBidi + ':' + wikiTextBlankOrBidi +&lt;br /&gt;
				( initial === '\\' || !HC.capitalizePageNames ?&lt;br /&gt;
					initial :&lt;br /&gt;
					'[' + initial.toUpperCase() + initial.toLowerCase() + ']' ) +&lt;br /&gt;
				cat_name.substring( 1 ).replace( wikiTextBlankRE, wikiTextBlank ) +&lt;br /&gt;
				wikiTextBlankOrBidi + '(\\|.*?)?\\]\\]',&lt;br /&gt;
				'g'&lt;br /&gt;
			);&lt;br /&gt;
		}&lt;br /&gt;
		if ( once ) return cat_regex.exec( wikitext );&lt;br /&gt;
&lt;br /&gt;
		var copiedtext = wikitext&lt;br /&gt;
			.replace( /&amp;lt;!--(\s|\S)*?--&amp;gt;/g, replaceByBlanks )&lt;br /&gt;
			.replace( /&amp;lt;nowiki&amp;gt;(\s|\S)*?&amp;lt;\/nowiki&amp;gt;/g, replaceByBlanks );&lt;br /&gt;
		var result = [];&lt;br /&gt;
		var curr_match = null;&lt;br /&gt;
		while ( ( curr_match = cat_regex.exec( copiedtext ) ) !== null ) {&lt;br /&gt;
			result.push( {&lt;br /&gt;
				match: curr_match&lt;br /&gt;
			} );&lt;br /&gt;
		}&lt;br /&gt;
		result.re = cat_regex;&lt;br /&gt;
		return result; // An array containing all matches, with positions, in result[ i ].match&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var interlanguageRE = null;&lt;br /&gt;
&lt;br /&gt;
	function change_category( wikitext, toRemove, toAdd, key, is_hidden ) {&lt;br /&gt;
&lt;br /&gt;
		function find_insertionpoint( wikitext ) {&lt;br /&gt;
			var copiedtext = wikitext&lt;br /&gt;
				.replace( /&amp;lt;!--(\s|\S)*?--&amp;gt;/g, replaceByBlanks )&lt;br /&gt;
				.replace( /&amp;lt;nowiki&amp;gt;(\s|\S)*?&amp;lt;\/nowiki&amp;gt;/g, replaceByBlanks );&lt;br /&gt;
			// Search in copiedtext to avoid that we insert inside an HTML comment or a nowiki &amp;quot;element&amp;quot;.&lt;br /&gt;
			var index = -1;&lt;br /&gt;
			findCatsRE.lastIndex = 0;&lt;br /&gt;
			while ( findCatsRE.exec( copiedtext ) !== null ) index = findCatsRE.lastIndex;&lt;br /&gt;
&lt;br /&gt;
			if ( index &amp;lt; 0 ) {&lt;br /&gt;
				// Find the index of the first interlanguage link...&lt;br /&gt;
				var match = null;&lt;br /&gt;
				if ( !interlanguageRE ) {&lt;br /&gt;
				// Approximation without API: interlanguage links start with 2 to 3 lower case letters, optionally followed by&lt;br /&gt;
				// a sequence of groups consisting of a dash followed by one or more lower case letters. Exceptions are &amp;quot;simple&amp;quot;&lt;br /&gt;
				// and &amp;quot;tokipona&amp;quot;.&lt;br /&gt;
					match = /((^|\n\r?)(\[\[\s*(([a-z]{2,3}(-[a-z]+)*)|simple|tokipona)\s*:[^\]]+\]\]\s*))+$/.exec( copiedtext );&lt;br /&gt;
				} else {&lt;br /&gt;
					match = interlanguageRE.exec( copiedtext );&lt;br /&gt;
				}&lt;br /&gt;
				if ( match ) index = match.index;&lt;br /&gt;
&lt;br /&gt;
				return {&lt;br /&gt;
					idx: index,&lt;br /&gt;
					onCat: false&lt;br /&gt;
				};&lt;br /&gt;
			}&lt;br /&gt;
			return {&lt;br /&gt;
				idx: index,&lt;br /&gt;
				onCat: index &amp;gt;= 0&lt;br /&gt;
			};&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		var summary = [];&lt;br /&gt;
		var nameSpace = HC.category_canonical;&lt;br /&gt;
		var cat_point = -1; // Position of removed category;&lt;br /&gt;
&lt;br /&gt;
		if ( key ) key = '|' + key;&lt;br /&gt;
&lt;br /&gt;
		var keyChange = ( toRemove &amp;amp;&amp;amp; toAdd &amp;amp;&amp;amp; toRemove === toAdd &amp;amp;&amp;amp; toAdd.length );&lt;br /&gt;
		var matches;&lt;br /&gt;
		if ( toRemove &amp;amp;&amp;amp; toRemove.length ) {&lt;br /&gt;
			matches = find_category( wikitext, toRemove );&lt;br /&gt;
			if ( !matches || !matches.length ) {&lt;br /&gt;
				return {&lt;br /&gt;
					text: wikitext,&lt;br /&gt;
					summary: summary,&lt;br /&gt;
					error: HC.messages.cat_notFound.replace( /\$1/g, toRemove )&lt;br /&gt;
				};&lt;br /&gt;
			} else {&lt;br /&gt;
				var before = wikitext.substring( 0, matches[ 0 ].match.index );&lt;br /&gt;
				var after = wikitext.substring( matches[ 0 ].match.index + matches[ 0 ].match[ 0 ].length );&lt;br /&gt;
				if ( matches.length &amp;gt; 1 ) {&lt;br /&gt;
				// Remove all occurrences in after&lt;br /&gt;
					matches.re.lastIndex = 0;&lt;br /&gt;
					after = after.replace( matches.re, '' );&lt;br /&gt;
				}&lt;br /&gt;
				if ( toAdd ) {&lt;br /&gt;
					nameSpace = matches[ 0 ].match[ 1 ] || nameSpace;&lt;br /&gt;
					if ( key === null ) key = matches[ 0 ].match[ 2 ];&lt;br /&gt;
				// Remember the category key, if any.&lt;br /&gt;
				}&lt;br /&gt;
				// Remove whitespace (properly): strip whitespace, but only up to the next line feed.&lt;br /&gt;
				// If we then have two linefeeds in a row, remove one. Otherwise, if we have two non-&lt;br /&gt;
				// whitespace characters, insert a blank.&lt;br /&gt;
				var i = before.length - 1;&lt;br /&gt;
				while ( i &amp;gt;= 0 &amp;amp;&amp;amp; before.charAt( i ) !== '\n' &amp;amp;&amp;amp; before.substr( i, 1 ).search( /\s/ ) &amp;gt;= 0 ) i--;&lt;br /&gt;
&lt;br /&gt;
				var j = 0;&lt;br /&gt;
				while ( j &amp;lt; after.length &amp;amp;&amp;amp; after.charAt( j ) !== '\n' &amp;amp;&amp;amp; after.substr( j, 1 ).search( /\s/ ) &amp;gt;= 0 ) j++;&lt;br /&gt;
&lt;br /&gt;
				if ( i &amp;gt;= 0 &amp;amp;&amp;amp; before.charAt( i ) === '\n' &amp;amp;&amp;amp; ( !after.length || j &amp;lt; after.length &amp;amp;&amp;amp; after.charAt( j ) === '\n' ) ) i--;&lt;br /&gt;
&lt;br /&gt;
				if ( i &amp;gt;= 0 ) before = before.substring( 0, i + 1 ); else before = '';&lt;br /&gt;
&lt;br /&gt;
				if ( j &amp;lt; after.length ) after = after.substring( j ); else after = '';&lt;br /&gt;
&lt;br /&gt;
				if (&lt;br /&gt;
					before.length &amp;amp;&amp;amp; before.substring( before.length - 1 ).search( /\S/ ) &amp;gt;= 0 &amp;amp;&amp;amp;&lt;br /&gt;
					after.length &amp;amp;&amp;amp; after.substr( 0, 1 ).search( /\S/ ) &amp;gt;= 0&lt;br /&gt;
				) {&lt;br /&gt;
					before += ' ';&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				cat_point = before.length;&lt;br /&gt;
				if ( cat_point === 0 &amp;amp;&amp;amp; after.length &amp;amp;&amp;amp; after.substr( 0, 1 ) === '\n' ) after = after.substr( 1 );&lt;br /&gt;
&lt;br /&gt;
				wikitext = before + after;&lt;br /&gt;
				if ( !keyChange ) {&lt;br /&gt;
					if ( HC.template_categories[ toRemove ] ) { summary.push( HC.messages.template_removed.replace( /\$1/g, toRemove ) ); } else { summary.push( HC.messages.cat_removed.replace( /\$1/g, toRemove ) ); }&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		if ( toAdd &amp;amp;&amp;amp; toAdd.length ) {&lt;br /&gt;
			matches = find_category( wikitext, toAdd );&lt;br /&gt;
			if ( matches &amp;amp;&amp;amp; matches.length ) {&lt;br /&gt;
				return {&lt;br /&gt;
					text: wikitext,&lt;br /&gt;
					summary: summary,&lt;br /&gt;
					error: HC.messages.cat_exists.replace( /\$1/g, toAdd )&lt;br /&gt;
				};&lt;br /&gt;
			} else {&lt;br /&gt;
				var onCat = false;&lt;br /&gt;
				if ( cat_point &amp;lt; 0 ) {&lt;br /&gt;
					var point = find_insertionpoint( wikitext );&lt;br /&gt;
					cat_point = point.idx;&lt;br /&gt;
					onCat = point.onCat;&lt;br /&gt;
				} else {&lt;br /&gt;
					onCat = true;&lt;br /&gt;
				}&lt;br /&gt;
				var newcatstring = '[[' + nameSpace + ':' + toAdd + ( key || '' ) + ']]';&lt;br /&gt;
				if ( cat_point &amp;gt;= 0 ) {&lt;br /&gt;
					var suffix = wikitext.substring( cat_point );&lt;br /&gt;
					wikitext = wikitext.substring( 0, cat_point ) + ( cat_point &amp;gt; 0 ? '\n' : '' ) + newcatstring + ( !onCat ? '\n' : '' );&lt;br /&gt;
					if ( suffix.length &amp;amp;&amp;amp; suffix.substr( 0, 1 ) !== '\n' ) wikitext += '\n' + suffix; else wikitext += suffix;&lt;br /&gt;
				} else {&lt;br /&gt;
					if ( wikitext.length &amp;amp;&amp;amp; wikitext.substr( wikitext.length - 1, 1 ) !== '\n' ) wikitext += '\n';&lt;br /&gt;
&lt;br /&gt;
					wikitext += ( wikitext.length ? '\n' : '' ) + newcatstring;&lt;br /&gt;
				}&lt;br /&gt;
				if ( keyChange ) {&lt;br /&gt;
					var k = key || '';&lt;br /&gt;
					if ( k.length ) k = k.substr( 1 );&lt;br /&gt;
&lt;br /&gt;
					summary.push( substitute( HC.messages.cat_keychange, [ null, toAdd, k ] ) );&lt;br /&gt;
				} else {&lt;br /&gt;
					summary.push( HC.messages.cat_added.replace( /\$1/g, toAdd ) );&lt;br /&gt;
				}&lt;br /&gt;
				if ( HC.uncat_regexp &amp;amp;&amp;amp; !is_hidden ) {&lt;br /&gt;
					var txt = wikitext.replace( HC.uncat_regexp, '' ); // Remove &amp;quot;uncat&amp;quot; templates&lt;br /&gt;
					if ( txt.length !== wikitext.length ) {&lt;br /&gt;
						wikitext = txt;&lt;br /&gt;
						summary.push( HC.messages.uncat_removed );&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return {&lt;br /&gt;
			text: wikitext,&lt;br /&gt;
			summary: summary,&lt;br /&gt;
			error: null&lt;br /&gt;
		};&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// The real HotCat UI&lt;br /&gt;
&lt;br /&gt;
	function evtKeys( e ) {&lt;br /&gt;
		/* eslint-disable no-bitwise */&lt;br /&gt;
		e = e || window.event; // W3C, IE&lt;br /&gt;
		var code = 0;&lt;br /&gt;
		if ( e.ctrlKey ) { // All modern browsers&lt;br /&gt;
		// Ctrl-click seems to be overloaded in FF/Mac (it opens a pop-up menu), so treat cmd-click&lt;br /&gt;
		// as a ctrl-click, too.&lt;br /&gt;
			if ( e.ctrlKey || e.metaKey ) code |= 1;&lt;br /&gt;
&lt;br /&gt;
			if ( e.shiftKey ) code |= 2;&lt;br /&gt;
		}&lt;br /&gt;
		return code;&lt;br /&gt;
	}&lt;br /&gt;
	function evtKill( e ) {&lt;br /&gt;
		e = e || window.event; // W3C, IE&lt;br /&gt;
		if ( e.preventDefault ) {&lt;br /&gt;
			e.preventDefault();&lt;br /&gt;
			e.stopPropagation();&lt;br /&gt;
		} else {&lt;br /&gt;
			e.cancelBubble = true;&lt;br /&gt;
		}&lt;br /&gt;
		return false;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var catLine = null,&lt;br /&gt;
		onUpload = false,&lt;br /&gt;
		editors = [],&lt;br /&gt;
&lt;br /&gt;
		commitButton = null,&lt;br /&gt;
		commitForm = null,&lt;br /&gt;
		multiSpan = null,&lt;br /&gt;
&lt;br /&gt;
		pageText = null,&lt;br /&gt;
		pageTime = null,&lt;br /&gt;
		pageWatched = false,&lt;br /&gt;
		watchCreate = false,&lt;br /&gt;
		watchEdit = false,&lt;br /&gt;
		minorEdits = false,&lt;br /&gt;
		editToken = null,&lt;br /&gt;
&lt;br /&gt;
		is_rtl = false,&lt;br /&gt;
		serverTime = null,&lt;br /&gt;
		lastRevId = null,&lt;br /&gt;
		pageTextRevId = null,&lt;br /&gt;
		conflictingUser = null,&lt;br /&gt;
&lt;br /&gt;
		newDOM = false; // true if MediaWiki serves the new UL-LI DOM for categories&lt;br /&gt;
&lt;br /&gt;
	function CategoryEditor() {&lt;br /&gt;
		this.initialize.apply( this, arguments );&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function setPage( json ) {&lt;br /&gt;
		var startTime = null;&lt;br /&gt;
		if ( json &amp;amp;&amp;amp; json.query ) {&lt;br /&gt;
			if ( json.query.pages ) {&lt;br /&gt;
				var page = json.query.pages[ !conf.wgArticleId ? '-1' : String( conf.wgArticleId ) ];&lt;br /&gt;
				if ( page ) {&lt;br /&gt;
					if ( page.revisions &amp;amp;&amp;amp; page.revisions.length ) {&lt;br /&gt;
						// Revisions are sorted by revision ID, hence [ 0 ] is the one we asked for, and possibly there's a [ 1 ] if we're&lt;br /&gt;
						// not on the latest revision (edit conflicts and such).&lt;br /&gt;
						pageText = page.revisions[ 0 ][ '*' ];&lt;br /&gt;
						if ( page.revisions[ 0 ].timestamp ) pageTime = page.revisions[ 0 ].timestamp.replace( /\D/g, '' );&lt;br /&gt;
						if ( page.revisions[ 0 ].revid ) pageTextRevId = page.revisions[ 0 ].revid;&lt;br /&gt;
						if ( page.revisions.length &amp;gt; 1 ) conflictingUser = page.revisions[ 1 ].user;&lt;br /&gt;
					}&lt;br /&gt;
					if ( page.lastrevid ) lastRevId = page.lastrevid;&lt;br /&gt;
					if ( page.starttimestamp ) startTime = page.starttimestamp.replace( /\D/g, '' );&lt;br /&gt;
					pageWatched = typeof page.watched === 'string';&lt;br /&gt;
					editToken = page.edittoken;&lt;br /&gt;
					if ( page.langlinks &amp;amp;&amp;amp; ( !json[ 'query-continue' ] || !json[ 'query-continue' ].langlinks ) ) {&lt;br /&gt;
						// We have interlanguage links, and we got them all.&lt;br /&gt;
						var re = '';&lt;br /&gt;
						for ( var i = 0; i &amp;lt; page.langlinks.length; i++ ) re += ( i &amp;gt; 0 ? '|' : '' ) + page.langlinks[ i ].lang.replace( /([\\^$.?*+()])/g, '\\$1' );&lt;br /&gt;
						if ( re.length ) interlanguageRE = new RegExp( '((^|\\n\\r?)(\\[\\[\\s*(' + re + ')\\s*:[^\\]]+\\]\\]\\s*))+$' );&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			// Siteinfo&lt;br /&gt;
			if ( json.query.general ) {&lt;br /&gt;
			// ResourceLoader's JSParser doesn't like .case, so override eslint.&lt;br /&gt;
			// eslint-disable-next-line dot-notation&lt;br /&gt;
				HC.capitalizePageNames = ( json.query.general[ 'case' ] === 'first-letter' );&lt;br /&gt;
				if ( json.query.general.time &amp;amp;&amp;amp; !startTime ) startTime = json.query.general.time.replace( /\D/g, '' );&lt;br /&gt;
			}&lt;br /&gt;
			serverTime = startTime;&lt;br /&gt;
			// Userinfo&lt;br /&gt;
			if ( json.query.userinfo &amp;amp;&amp;amp; json.query.userinfo.options ) {&lt;br /&gt;
				watchCreate = !HC.dont_add_to_watchlist &amp;amp;&amp;amp; json.query.userinfo.options.watchcreations === '1';&lt;br /&gt;
				watchEdit = !HC.dont_add_to_watchlist &amp;amp;&amp;amp; json.query.userinfo.options.watchdefault === '1';&lt;br /&gt;
				minorEdits = json.query.userinfo.options.minordefault === 1;&lt;br /&gt;
				// If the user has the &amp;quot;All edits are minor&amp;quot; preference enabled, we should honor that&lt;br /&gt;
				// for single category changes, no matter what the site configuration is.&lt;br /&gt;
				if ( minorEdits ) HC.single_minor = true;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var saveInProgress = false;&lt;br /&gt;
	function initiateEdit( doEdit, failure ) {&lt;br /&gt;
		if ( saveInProgress ) return;&lt;br /&gt;
		saveInProgress = true;&lt;br /&gt;
		var oldButtonState;&lt;br /&gt;
		if ( commitButton ) {&lt;br /&gt;
			oldButtonState = commitButton.disabled;&lt;br /&gt;
			commitButton.disabled = true;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		function fail() {&lt;br /&gt;
			saveInProgress = false;&lt;br /&gt;
			if ( commitButton ) commitButton.disabled = oldButtonState;&lt;br /&gt;
			failure.apply( this, arguments );&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Must use Ajax here to get the user options and the edit token.&lt;br /&gt;
		$.getJSON(&lt;br /&gt;
			conf.wgServer + conf.wgScriptPath + '/api.php?' +&lt;br /&gt;
			'format=json&amp;amp;action=query&amp;amp;rawcontinue=&amp;amp;titles=' + encodeURIComponent( conf.wgPageName ) +&lt;br /&gt;
			'&amp;amp;prop=info%7Crevisions%7Clanglinks&amp;amp;inprop=watched&amp;amp;intoken=edit&amp;amp;rvprop=content%7Ctimestamp%7Cids%7Cuser&amp;amp;lllimit=500' +&lt;br /&gt;
			'&amp;amp;rvlimit=2&amp;amp;rvdir=newer&amp;amp;rvstartid=' + conf.wgCurRevisionId +	'&amp;amp;meta=siteinfo%7Cuserinfo&amp;amp;uiprop=options',&lt;br /&gt;
			function ( json ) {&lt;br /&gt;
				setPage( json );&lt;br /&gt;
				doEdit( fail );&lt;br /&gt;
			}&lt;br /&gt;
		).fail( function ( req ) {&lt;br /&gt;
			fail( req.status + ' ' + req.statusText );&lt;br /&gt;
		} );&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function multiChangeMsg( count ) {&lt;br /&gt;
		var msg = HC.messages.multi_change;&lt;br /&gt;
		if ( typeof msg !== 'string' &amp;amp;&amp;amp; msg.length )&lt;br /&gt;
			if ( mw.language &amp;amp;&amp;amp; mw.language.convertPlural ) { msg = mw.language.convertPlural( count, msg ); } else { msg = msg[ msg.length - 1 ]; }&lt;br /&gt;
&lt;br /&gt;
		return substitute( msg, [ null, String( count ) ] );&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function currentTimestamp() {&lt;br /&gt;
		var now = new Date();&lt;br /&gt;
		var ts = String( now.getUTCFullYear() );&lt;br /&gt;
		function two( s ) {&lt;br /&gt;
			return s.substr( s.length - 2 );&lt;br /&gt;
		}&lt;br /&gt;
		ts +=&lt;br /&gt;
			two( '0' + ( now.getUTCMonth() + 1 ) ) +&lt;br /&gt;
			two( '0' + now.getUTCDate() ) +&lt;br /&gt;
			two( '00' + now.getUTCHours() ) +&lt;br /&gt;
			two( '00' + now.getUTCMinutes() ) +&lt;br /&gt;
			two( '00' + now.getUTCSeconds() );&lt;br /&gt;
		return ts;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function performChanges( failure, singleEditor ) {&lt;br /&gt;
		if ( pageText === null ) {&lt;br /&gt;
			failure( HC.messages.multi_error );&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		// Backwards compatibility after message change (added $2 to cat_keychange)&lt;br /&gt;
		if ( HC.messages.cat_keychange.indexOf( '$2' ) &amp;lt; 0 ) HC.messages.cat_keychange += '&amp;quot;$2&amp;quot;';&lt;br /&gt;
&lt;br /&gt;
		// More backwards-compatibility with earlier HotCat versions:&lt;br /&gt;
		if ( !HC.messages.short_catchange ) HC.messages.short_catchange = '[[' + HC.category_canonical + ':$1]]';&lt;br /&gt;
&lt;br /&gt;
		// Create a form and submit it. We don't use the edit API (api.php?action=edit) because&lt;br /&gt;
		// (a) sensibly reporting back errors like edit conflicts is always a hassle, and&lt;br /&gt;
		// (b) we want to show a diff for multi-edits anyway, and&lt;br /&gt;
		// (c) we want to trigger onsubmit events, allowing user code to intercept the edit.&lt;br /&gt;
		// Using the form, we can do (b) and (c), and we get (a) for free. And, of course, using the form&lt;br /&gt;
		// automatically reloads the page with the updated categories on a successful submit, which&lt;br /&gt;
		// we would have to do explicitly if we used the edit API.&lt;br /&gt;
		var action;&lt;br /&gt;
		// Normally, we don't have to care about edit conflicts. If some other user edited the page in the meantime, the&lt;br /&gt;
		// server will take care of it and merge the edit automatically or present an edit conflict screen. However, the&lt;br /&gt;
		// server suppresses edit conflicts with oneself. Hence, if we have a conflict, and the conflicting user is the&lt;br /&gt;
		// current user, then we set the &amp;quot;oldid&amp;quot; value and switch to diff, which gives the &amp;quot;you are editing an old version;&lt;br /&gt;
		// if you save, any more recent changes will be lost&amp;quot; screen.&lt;br /&gt;
		var selfEditConflict = ( lastRevId !== null &amp;amp;&amp;amp; lastRevId !== conf.wgCurRevisionId || pageTextRevId !== null &amp;amp;&amp;amp;&lt;br /&gt;
			pageTextRevId !== conf.wgCurRevisionId ) &amp;amp;&amp;amp; conflictingUser &amp;amp;&amp;amp; conflictingUser === conf.wgUserName;&lt;br /&gt;
		if ( singleEditor &amp;amp;&amp;amp; !singleEditor.noCommit &amp;amp;&amp;amp; !HC.no_autocommit &amp;amp;&amp;amp; editToken &amp;amp;&amp;amp; !selfEditConflict ) {&lt;br /&gt;
			// If we do have an edit conflict, but not with ourself, that's no reason not to attempt to save: the server side may actually be able to&lt;br /&gt;
			// merge the changes. We just need to make sure that we do present a diff view if it's a self edit conflict.&lt;br /&gt;
			commitForm.wpEditToken.value = editToken;&lt;br /&gt;
			action = commitForm.wpDiff;&lt;br /&gt;
			if ( action ) action.name = action.value = 'wpSave';&lt;br /&gt;
		} else {&lt;br /&gt;
			action = commitForm.wpSave;&lt;br /&gt;
			if ( action ) action.name = action.value = 'wpDiff';&lt;br /&gt;
		}&lt;br /&gt;
		var result = {&lt;br /&gt;
				text: pageText&lt;br /&gt;
			},&lt;br /&gt;
			changed = [],&lt;br /&gt;
			added = [],&lt;br /&gt;
			deleted = [],&lt;br /&gt;
			changes = 0,&lt;br /&gt;
			toEdit = singleEditor ? [ singleEditor ] : editors,&lt;br /&gt;
			error = null,&lt;br /&gt;
			edit,&lt;br /&gt;
			i;&lt;br /&gt;
		for ( i = 0; i &amp;lt; toEdit.length; i++ ) {&lt;br /&gt;
			edit = toEdit[ i ];&lt;br /&gt;
			if ( edit.state === CategoryEditor.CHANGED ) {&lt;br /&gt;
				result = change_category(&lt;br /&gt;
					result.text,&lt;br /&gt;
					edit.originalCategory,&lt;br /&gt;
					edit.currentCategory,&lt;br /&gt;
					edit.currentKey,&lt;br /&gt;
					edit.currentHidden );&lt;br /&gt;
				if ( !result.error ) {&lt;br /&gt;
					changes++;&lt;br /&gt;
					if ( !edit.originalCategory || !edit.originalCategory.length ) {&lt;br /&gt;
						added.push( edit.currentCategory );&lt;br /&gt;
					} else {&lt;br /&gt;
						changed.push( {&lt;br /&gt;
							from: edit.originalCategory,&lt;br /&gt;
							to: edit.currentCategory&lt;br /&gt;
						} );&lt;br /&gt;
					}&lt;br /&gt;
				} else if ( error === null ) {&lt;br /&gt;
					error = result.error;&lt;br /&gt;
				}&lt;br /&gt;
			} else if (&lt;br /&gt;
				edit.state === CategoryEditor.DELETED &amp;amp;&amp;amp; edit.originalCategory &amp;amp;&amp;amp; edit.originalCategory.length ) {&lt;br /&gt;
				result = change_category(&lt;br /&gt;
					result.text,&lt;br /&gt;
					edit.originalCategory,&lt;br /&gt;
					null, null, false );&lt;br /&gt;
				if ( !result.error ) {&lt;br /&gt;
					changes++;&lt;br /&gt;
					deleted.push( edit.originalCategory );&lt;br /&gt;
				} else if ( error === null ) {&lt;br /&gt;
					error = result.error;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		if ( error !== null ) { // Do not commit if there were errors&lt;br /&gt;
			action = commitForm.wpSave;&lt;br /&gt;
			if ( action ) action.name = action.value = 'wpDiff';&lt;br /&gt;
		}&lt;br /&gt;
		// Fill in the form and submit it&lt;br /&gt;
		commitForm.wpMinoredit.checked = minorEdits;&lt;br /&gt;
		commitForm.wpWatchthis.checked = !conf.wgArticleId &amp;amp;&amp;amp; watchCreate || watchEdit || pageWatched;&lt;br /&gt;
		if ( conf.wgArticleId || !!singleEditor ) {&lt;br /&gt;
			// Prepare change-tag save&lt;br /&gt;
			if ( action &amp;amp;&amp;amp; action.value === 'wpSave' ) {&lt;br /&gt;
				if ( HC.changeTag ) {&lt;br /&gt;
					commitForm.wpChangeTags.value = HC.changeTag;&lt;br /&gt;
					HC.messages.using = '';&lt;br /&gt;
					HC.messages.prefix = '';&lt;br /&gt;
				}&lt;br /&gt;
			} else {&lt;br /&gt;
				commitForm.wpAutoSummary.value = HC.changeTag;&lt;br /&gt;
			}&lt;br /&gt;
			if ( changes === 1 ) {&lt;br /&gt;
				if ( result.summary &amp;amp;&amp;amp; result.summary.length ) commitForm.wpSummary.value = HC.messages.prefix + result.summary.join( HC.messages.separator ) + HC.messages.using;&lt;br /&gt;
				commitForm.wpMinoredit.checked = HC.single_minor || minorEdits;&lt;br /&gt;
			} else if ( changes ) {&lt;br /&gt;
				var summary = [];&lt;br /&gt;
				var shortSummary = [];&lt;br /&gt;
				// Deleted&lt;br /&gt;
				for ( i = 0; i &amp;lt; deleted.length; i++ ) summary.push( '-' + substitute( HC.messages.short_catchange, [ null, deleted[ i ] ] ) );&lt;br /&gt;
&lt;br /&gt;
				if ( deleted.length === 1 ) shortSummary.push( '-' + substitute( HC.messages.short_catchange, [ null, deleted[ 0 ] ] ) ); else if ( deleted.length ) shortSummary.push( '- ' + multiChangeMsg( deleted.length ) );&lt;br /&gt;
&lt;br /&gt;
				// Added&lt;br /&gt;
				for ( i = 0; i &amp;lt; added.length; i++ ) summary.push( '+' + substitute( HC.messages.short_catchange, [ null, added[ i ] ] ) );&lt;br /&gt;
&lt;br /&gt;
				if ( added.length === 1 ) shortSummary.push( '+' + substitute( HC.messages.short_catchange, [ null, added[ 0 ] ] ) ); else if ( added.length ) shortSummary.push( '+ ' + multiChangeMsg( added.length ) );&lt;br /&gt;
&lt;br /&gt;
				// Changed&lt;br /&gt;
				var arrow = is_rtl ? '\u2190' : '\u2192'; // left and right arrows. Don't use ← and → in the code.&lt;br /&gt;
				for ( i = 0; i &amp;lt; changed.length; i++ ) {&lt;br /&gt;
					if ( changed[ i ].from !== changed[ i ].to ) {&lt;br /&gt;
						summary.push(&lt;br /&gt;
							'±' + substitute( HC.messages.short_catchange, [ null, changed[ i ].from ] ) + arrow +&lt;br /&gt;
							substitute( HC.messages.short_catchange, [ null, changed[ i ].to ] )&lt;br /&gt;
						);&lt;br /&gt;
					} else {&lt;br /&gt;
						summary.push( '±' + substitute( HC.messages.short_catchange, [ null, changed[ i ].from ] ) );&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				if ( changed.length === 1 ) {&lt;br /&gt;
					if ( changed[ 0 ].from !== changed[ 0 ].to ) {&lt;br /&gt;
						shortSummary.push(&lt;br /&gt;
							'±' + substitute( HC.messages.short_catchange, [ null, changed[ 0 ].from ] ) + arrow +&lt;br /&gt;
							substitute( HC.messages.short_catchange, [ null, changed[ 0 ].to ] )&lt;br /&gt;
						);&lt;br /&gt;
					} else {&lt;br /&gt;
						shortSummary.push( '±' + substitute( HC.messages.short_catchange, [ null, changed[ 0 ].from ] ) );&lt;br /&gt;
					}&lt;br /&gt;
				} else if ( changed.length ) {&lt;br /&gt;
					shortSummary.push( '± ' + multiChangeMsg( changed.length ) );&lt;br /&gt;
				}&lt;br /&gt;
				if ( summary.length ) {&lt;br /&gt;
					summary = summary.join( HC.messages.separator );&lt;br /&gt;
					if ( summary.length &amp;gt; 200 - HC.messages.prefix.length - HC.messages.using.length ) summary = shortSummary.join( HC.messages.separator );&lt;br /&gt;
&lt;br /&gt;
					commitForm.wpSummary.value = HC.messages.prefix + summary + HC.messages.using;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		commitForm.wpTextbox1.value = result.text;&lt;br /&gt;
		commitForm.wpStarttime.value = serverTime || currentTimestamp();&lt;br /&gt;
		commitForm.wpEdittime.value = pageTime || commitForm.wpStarttime.value;&lt;br /&gt;
		if ( selfEditConflict ) commitForm.oldid.value = String( pageTextRevId || conf.wgCurRevisionId );&lt;br /&gt;
&lt;br /&gt;
		// Submit the form in a way that triggers onsubmit events: commitForm.submit() doesn't.&lt;br /&gt;
		commitForm.hcCommit.click();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function resolveOne( page, toResolve ) {&lt;br /&gt;
		var cats = page.categories,&lt;br /&gt;
			lks = page.links,&lt;br /&gt;
			is_dab = false,&lt;br /&gt;
			is_redir = typeof page.redirect === 'string', // Hard redirect?&lt;br /&gt;
			is_hidden = page.categoryinfo &amp;amp;&amp;amp; typeof page.categoryinfo.hidden === 'string',&lt;br /&gt;
			is_missing = typeof page.missing === 'string',&lt;br /&gt;
			i;&lt;br /&gt;
		for ( i = 0; i &amp;lt; toResolve.length; i++ ) {&lt;br /&gt;
			if ( i &amp;amp;&amp;amp; toResolve[ i ].dabInputCleaned !== page.title.substring( page.title.indexOf( ':' ) + 1 ) ) continue;&lt;br /&gt;
			// Note: the server returns in page an NFC normalized Unicode title. If our input was not NFC normalized, we may not find&lt;br /&gt;
			// any entry here. If we have only one editor to resolve (the most common case, I presume), we may simply skip the check.&lt;br /&gt;
			toResolve[ i ].currentHidden = is_hidden;&lt;br /&gt;
			toResolve[ i ].inputExists = !is_missing;&lt;br /&gt;
			toResolve[ i ].icon.src = armorUri( is_missing ? HC.existsNo : HC.existsYes );&lt;br /&gt;
		}&lt;br /&gt;
		if ( is_missing ) return;&lt;br /&gt;
		if ( !is_redir &amp;amp;&amp;amp; cats &amp;amp;&amp;amp; ( HC.disambig_category || HC.redir_category ) ) {&lt;br /&gt;
			for ( var c = 0; c &amp;lt; cats.length; c++ ) {&lt;br /&gt;
				var cat = cats[ c ].title;&lt;br /&gt;
				// Strip namespace prefix&lt;br /&gt;
				if ( cat ) {&lt;br /&gt;
					cat = cat.substring( cat.indexOf( ':' ) + 1 ).replace( /_/g, ' ' );&lt;br /&gt;
					if ( cat === HC.disambig_category ) {&lt;br /&gt;
						is_dab = true;&lt;br /&gt;
						break;&lt;br /&gt;
					} else if ( cat === HC.redir_category ) {&lt;br /&gt;
						is_redir = true;&lt;br /&gt;
						break;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		if ( !is_redir &amp;amp;&amp;amp; !is_dab ) return;&lt;br /&gt;
		if ( !lks || !lks.length ) return;&lt;br /&gt;
		var titles = [];&lt;br /&gt;
		for ( i = 0; i &amp;lt; lks.length; i++ ) {&lt;br /&gt;
			if (&lt;br /&gt;
				// Category namespace -- always true since we ask only for the category links&lt;br /&gt;
				lks[ i ].ns === 14 &amp;amp;&amp;amp;&lt;br /&gt;
				// Name not empty&lt;br /&gt;
				lks[ i ].title &amp;amp;&amp;amp; lks[ i ].title.length&lt;br /&gt;
			) {&lt;br /&gt;
				// Internal link to existing thingy. Extract the page name and remove the namespace.&lt;br /&gt;
				var match = lks[ i ].title;&lt;br /&gt;
				match = match.substring( match.indexOf( ':' ) + 1 );&lt;br /&gt;
				// Exclude blacklisted categories.&lt;br /&gt;
				if ( !HC.blacklist || !HC.blacklist.test( match ) ) titles.push( match );&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		if ( !titles.length ) return;&lt;br /&gt;
		for ( i = 0; i &amp;lt; toResolve.length; i++ ) {&lt;br /&gt;
			if ( i &amp;amp;&amp;amp; toResolve[ i ].dabInputCleaned !== page.title.substring( page.title.indexOf( ':' ) + 1 ) ) continue;&lt;br /&gt;
			toResolve[ i ].inputExists = true; // Might actually be wrong if it's a redirect pointing to a non-existing category&lt;br /&gt;
			toResolve[ i ].icon.src = armorUri( HC.existsYes );&lt;br /&gt;
			if ( titles.length &amp;gt; 1 ) {&lt;br /&gt;
				toResolve[ i ].dab = titles;&lt;br /&gt;
			} else {&lt;br /&gt;
				toResolve[ i ].text.value =&lt;br /&gt;
					titles[ 0 ] + ( toResolve[ i ].currentKey !== null ? '|' + toResolve[ i ].currentKey : '' );&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function resolveRedirects( toResolve, params ) {&lt;br /&gt;
		if ( !params || !params.query || !params.query.pages ) return;&lt;br /&gt;
		for ( var p in params.query.pages ) resolveOne( params.query.pages[ p ], toResolve );&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function resolveMulti( toResolve, callback ) {&lt;br /&gt;
		var i;&lt;br /&gt;
		for ( i = 0; i &amp;lt; toResolve.length; i++ ) {&lt;br /&gt;
			toResolve[ i ].dab = null;&lt;br /&gt;
			toResolve[ i ].dabInput = toResolve[ i ].lastInput;&lt;br /&gt;
		}&lt;br /&gt;
		if ( noSuggestions ) {&lt;br /&gt;
			callback( toResolve );&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		// Use %7C instead of |, otherwise Konqueror insists on re-encoding the arguments, resulting in doubly encoded&lt;br /&gt;
		// category names. (That is a bug in Konqueror. Other browsers don't have this problem.)&lt;br /&gt;
		var args = 'action=query&amp;amp;prop=info%7Clinks%7Ccategories%7Ccategoryinfo&amp;amp;plnamespace=14' +&lt;br /&gt;
			'&amp;amp;pllimit=' + ( toResolve.length * 10 ) +&lt;br /&gt;
			'&amp;amp;cllimit=' + ( toResolve.length * 10 ) +&lt;br /&gt;
			'&amp;amp;format=json&amp;amp;titles=';&lt;br /&gt;
		for ( i = 0; i &amp;lt; toResolve.length; i++ ) {&lt;br /&gt;
			var v = toResolve[ i ].dabInput;&lt;br /&gt;
			v = replaceShortcuts( v, HC.shortcuts );&lt;br /&gt;
			toResolve[ i ].dabInputCleaned = v;&lt;br /&gt;
			args += encodeURIComponent( 'Category:' + v );&lt;br /&gt;
			if ( i + 1 &amp;lt; toResolve.length ) args += '%7C';&lt;br /&gt;
		}&lt;br /&gt;
		$.getJSON( conf.wgServer + conf.wgScriptPath + '/api.php?' + args,&lt;br /&gt;
			function ( json ) {&lt;br /&gt;
				resolveRedirects( toResolve, json );&lt;br /&gt;
				callback( toResolve );&lt;br /&gt;
			} ).fail( function ( req ) {&lt;br /&gt;
			if ( !req ) noSuggestions = true;&lt;br /&gt;
			callback( toResolve );&lt;br /&gt;
		} );&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function makeActive( which ) {&lt;br /&gt;
		if ( which.is_active ) return;&lt;br /&gt;
		for ( var i = 0; i &amp;lt; editors.length; i++ )&lt;br /&gt;
			if ( editors[ i ] !== which ) editors[ i ].inactivate();&lt;br /&gt;
&lt;br /&gt;
		which.is_active = true;&lt;br /&gt;
		if ( which.dab ) {&lt;br /&gt;
			// eslint-disable-next-line no-use-before-define&lt;br /&gt;
			showDab( which );&lt;br /&gt;
		} else {&lt;br /&gt;
			// Check for programmatic value changes.&lt;br /&gt;
			var expectedInput = which.lastRealInput || which.lastInput || '';&lt;br /&gt;
			var actualValue = which.text.value || '';&lt;br /&gt;
			if ( !expectedInput.length &amp;amp;&amp;amp; actualValue.length || expectedInput.length &amp;amp;&amp;amp; actualValue.indexOf( expectedInput ) ) {&lt;br /&gt;
				// Somehow the field's value appears to have changed, and which.lastSelection therefore is no longer valid. Try to set the&lt;br /&gt;
				// cursor at the end of the category, and do not display the old suggestion list.&lt;br /&gt;
				which.showsList = false;&lt;br /&gt;
				var v = actualValue.split( '|' );&lt;br /&gt;
				which.lastRealInput = which.lastInput = v[ 0 ];&lt;br /&gt;
				if ( v.length &amp;gt; 1 ) which.currentKey = v[ 1 ];&lt;br /&gt;
&lt;br /&gt;
				if ( which.lastSelection ) {&lt;br /&gt;
					which.lastSelection = {&lt;br /&gt;
						start: v[ 0 ].length,&lt;br /&gt;
						end: v[ 0 ].length&lt;br /&gt;
					};&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			if ( which.showsList ) which.displayList();&lt;br /&gt;
&lt;br /&gt;
			if ( which.lastSelection ) {&lt;br /&gt;
				if ( is_webkit ) {&lt;br /&gt;
					// WebKit (Safari, Chrome) has problems selecting inside focus()&lt;br /&gt;
					// See http://code.google.com/p/chromium/issues/detail?id=32865#c6&lt;br /&gt;
					window.setTimeout(&lt;br /&gt;
						function () {&lt;br /&gt;
							which.setSelection( which.lastSelection.start, which.lastSelection.end );&lt;br /&gt;
						},&lt;br /&gt;
						1 );&lt;br /&gt;
				} else {&lt;br /&gt;
					which.setSelection( which.lastSelection.start, which.lastSelection.end );&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function showDab( which ) {&lt;br /&gt;
		if ( !which.is_active ) {&lt;br /&gt;
			makeActive( which );&lt;br /&gt;
		} else {&lt;br /&gt;
			which.showSuggestions( which.dab, false, null, null ); // do autocompletion, no key, no engine selector&lt;br /&gt;
			which.dab = null;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function multiSubmit() {&lt;br /&gt;
		var toResolve = [];&lt;br /&gt;
		for ( var i = 0; i &amp;lt; editors.length; i++ )&lt;br /&gt;
			if ( editors[ i ].state === CategoryEditor.CHANGE_PENDING || editors[ i ].state === CategoryEditor.OPEN ) toResolve.push( editors[ i ] );&lt;br /&gt;
&lt;br /&gt;
		if ( !toResolve.length ) {&lt;br /&gt;
			initiateEdit( function ( failure ) {&lt;br /&gt;
				performChanges( failure );&lt;br /&gt;
			}, function ( msg ) {&lt;br /&gt;
				alert( msg );&lt;br /&gt;
			} );&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		resolveMulti( toResolve, function ( resolved ) {&lt;br /&gt;
			var firstDab = null;&lt;br /&gt;
			var dontChange = false;&lt;br /&gt;
			for ( var i = 0; i &amp;lt; resolved.length; i++ ) {&lt;br /&gt;
				if ( resolved[ i ].lastInput !== resolved[ i ].dabInput ) {&lt;br /&gt;
					// We didn't disable all the open editors, but we did asynchronous calls. It is&lt;br /&gt;
					// theoretically possible that the user changed something...&lt;br /&gt;
					dontChange = true;&lt;br /&gt;
				} else {&lt;br /&gt;
					if ( resolved[ i ].dab ) {&lt;br /&gt;
						if ( !firstDab ) firstDab = resolved[ i ];&lt;br /&gt;
					} else {&lt;br /&gt;
						if ( resolved[ i ].acceptCheck( true ) ) resolved[ i ].commit();&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			if ( firstDab ) {&lt;br /&gt;
				showDab( firstDab );&lt;br /&gt;
			} else if ( !dontChange ) {&lt;br /&gt;
				initiateEdit( function ( failure ) {&lt;br /&gt;
					performChanges( failure );&lt;br /&gt;
				}, function ( msg ) {&lt;br /&gt;
					alert( msg );&lt;br /&gt;
				} );&lt;br /&gt;
			}&lt;br /&gt;
		} );&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function setMultiInput() {&lt;br /&gt;
		if ( commitButton || onUpload ) return;&lt;br /&gt;
		commitButton = make( 'input' );&lt;br /&gt;
		commitButton.type = 'button';&lt;br /&gt;
		commitButton.value = HC.messages.commit;&lt;br /&gt;
		commitButton.onclick = multiSubmit;&lt;br /&gt;
		if ( multiSpan ) multiSpan.parentNode.replaceChild( commitButton, multiSpan ); else catLine.appendChild( commitButton );&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function checkMultiInput() {&lt;br /&gt;
		if ( !commitButton ) return;&lt;br /&gt;
		var hasChanges = false;&lt;br /&gt;
		for ( var i = 0; i &amp;lt; editors.length; i++ ) {&lt;br /&gt;
			if ( editors[ i ].state !== CategoryEditor.UNCHANGED ) {&lt;br /&gt;
				hasChanges = true;&lt;br /&gt;
				break;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		commitButton.disabled = !hasChanges;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var suggestionEngines = {&lt;br /&gt;
		opensearch: {&lt;br /&gt;
			uri: '/api.php?format=json&amp;amp;action=opensearch&amp;amp;namespace=14&amp;amp;limit=30&amp;amp;search=Category:$1', // $1 = search term&lt;br /&gt;
			// Function to convert result of uri into an array of category names&lt;br /&gt;
			handler: function ( queryResult, queryKey ) {&lt;br /&gt;
				if ( queryResult &amp;amp;&amp;amp; queryResult.length &amp;gt;= 2 ) {&lt;br /&gt;
					var key = queryResult[ 0 ].substring( queryResult[ 0 ].indexOf( ':' ) + 1 );&lt;br /&gt;
					var titles = queryResult[ 1 ];&lt;br /&gt;
					var exists = false;&lt;br /&gt;
					if ( !cat_prefix ) cat_prefix = new RegExp( '^(' + HC.category_regexp + '):' );&lt;br /&gt;
&lt;br /&gt;
					for ( var i = 0; i &amp;lt; titles.length; i++ ) {&lt;br /&gt;
						cat_prefix.lastIndex = 0;&lt;br /&gt;
						var m = cat_prefix.exec( titles[ i ] );&lt;br /&gt;
						if ( m &amp;amp;&amp;amp; m.length &amp;gt; 1 ) {&lt;br /&gt;
							titles[ i ] = titles[ i ].substring( titles[ i ].indexOf( ':' ) + 1 ); // rm namespace&lt;br /&gt;
							if ( key === titles[ i ] ) exists = true;&lt;br /&gt;
						} else {&lt;br /&gt;
							titles.splice( i, 1 ); // Nope, it's not a category after all.&lt;br /&gt;
							i--;&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
					titles.exists = exists;&lt;br /&gt;
					if ( queryKey !== key ) titles.normalized = key;&lt;br /&gt;
					// Remember the NFC normalized key we got back from the server&lt;br /&gt;
					return titles;&lt;br /&gt;
				}&lt;br /&gt;
				return null;&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
		internalsearch: {&lt;br /&gt;
			uri: '/api.php?format=json&amp;amp;action=query&amp;amp;list=allpages&amp;amp;apnamespace=14&amp;amp;aplimit=30&amp;amp;apfrom=$1&amp;amp;apprefix=$1',&lt;br /&gt;
			handler: function ( queryResult ) {&lt;br /&gt;
				if ( queryResult &amp;amp;&amp;amp; queryResult.query &amp;amp;&amp;amp; queryResult.query.allpages ) {&lt;br /&gt;
					var titles = queryResult.query.allpages;&lt;br /&gt;
					for ( var i = 0; i &amp;lt; titles.length; i++ ) titles[ i ] = titles[ i ].title.substring( titles[ i ].title.indexOf( ':' ) + 1 ); // rm namespace&lt;br /&gt;
&lt;br /&gt;
					return titles;&lt;br /&gt;
				}&lt;br /&gt;
				return null;&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
		exists: {&lt;br /&gt;
			uri: '/api.php?format=json&amp;amp;action=query&amp;amp;prop=info&amp;amp;titles=Category:$1',&lt;br /&gt;
			handler: function ( queryResult, queryKey ) {&lt;br /&gt;
				if ( queryResult &amp;amp;&amp;amp; queryResult.query &amp;amp;&amp;amp; queryResult.query.pages &amp;amp;&amp;amp; !queryResult.query.pages[ -1 ] ) {&lt;br /&gt;
					// Should have exactly 1&lt;br /&gt;
					for ( var p in queryResult.query.pages ) {&lt;br /&gt;
						var title = queryResult.query.pages[ p ].title;&lt;br /&gt;
						title = title.substring( title.indexOf( ':' ) + 1 );&lt;br /&gt;
						var titles = [ title ];&lt;br /&gt;
						titles.exists = true;&lt;br /&gt;
						if ( queryKey !== title ) titles.normalized = title;&lt;br /&gt;
						// NFC&lt;br /&gt;
						return titles;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				return null;&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
		subcategories: {&lt;br /&gt;
			uri: '/api.php?format=json&amp;amp;action=query&amp;amp;list=categorymembers&amp;amp;cmtype=subcat&amp;amp;cmlimit=max&amp;amp;cmtitle=Category:$1',&lt;br /&gt;
			handler: function ( queryResult ) {&lt;br /&gt;
				if ( queryResult &amp;amp;&amp;amp; queryResult.query &amp;amp;&amp;amp; queryResult.query.categorymembers ) {&lt;br /&gt;
					var titles = queryResult.query.categorymembers;&lt;br /&gt;
					for ( var i = 0; i &amp;lt; titles.length; i++ ) titles[ i ] = titles[ i ].title.substring( titles[ i ].title.indexOf( ':' ) + 1 ); // rm namespace&lt;br /&gt;
&lt;br /&gt;
					return titles;&lt;br /&gt;
				}&lt;br /&gt;
				return null;&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
		parentcategories: {&lt;br /&gt;
			uri: '/api.php?format=json&amp;amp;action=query&amp;amp;prop=categories&amp;amp;titles=Category:$1&amp;amp;cllimit=max',&lt;br /&gt;
			handler: function ( queryResult ) {&lt;br /&gt;
				if ( queryResult &amp;amp;&amp;amp; queryResult.query &amp;amp;&amp;amp; queryResult.query.pages ) {&lt;br /&gt;
					for ( var p in queryResult.query.pages ) {&lt;br /&gt;
						if ( queryResult.query.pages[ p ].categories ) {&lt;br /&gt;
							var titles = queryResult.query.pages[ p ].categories;&lt;br /&gt;
							for ( var i = 0; i &amp;lt; titles.length; i++ ) titles[ i ] = titles[ i ].title.substring( titles[ i ].title.indexOf( ':' ) + 1 ); // rm namespace&lt;br /&gt;
&lt;br /&gt;
							return titles;&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				return null;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	var suggestionConfigs = {&lt;br /&gt;
		searchindex: {&lt;br /&gt;
			name: 'Search index',&lt;br /&gt;
			engines: [ 'opensearch' ],&lt;br /&gt;
			cache: {},&lt;br /&gt;
			show: true,&lt;br /&gt;
			temp: false,&lt;br /&gt;
			noCompletion: false&lt;br /&gt;
		},&lt;br /&gt;
		pagelist: {&lt;br /&gt;
			name: 'Page list',&lt;br /&gt;
			engines: [ 'internalsearch', 'exists' ],&lt;br /&gt;
			cache: {},&lt;br /&gt;
			show: true,&lt;br /&gt;
			temp: false,&lt;br /&gt;
			noCompletion: false&lt;br /&gt;
		},&lt;br /&gt;
		combined: {&lt;br /&gt;
			name: 'Combined search',&lt;br /&gt;
			engines: [ 'opensearch', 'internalsearch' ],&lt;br /&gt;
			cache: {},&lt;br /&gt;
			show: true,&lt;br /&gt;
			temp: false,&lt;br /&gt;
			noCompletion: false&lt;br /&gt;
		},&lt;br /&gt;
		subcat: {&lt;br /&gt;
			name: 'Subcategories',&lt;br /&gt;
			engines: [ 'subcategories' ],&lt;br /&gt;
			cache: {},&lt;br /&gt;
			show: true,&lt;br /&gt;
			temp: true,&lt;br /&gt;
			noCompletion: true&lt;br /&gt;
		},&lt;br /&gt;
		parentcat: {&lt;br /&gt;
			name: 'Parent categories',&lt;br /&gt;
			engines: [ 'parentcategories' ],&lt;br /&gt;
			cache: {},&lt;br /&gt;
			show: true,&lt;br /&gt;
			temp: true,&lt;br /&gt;
			noCompletion: true&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	CategoryEditor.UNCHANGED = 0;&lt;br /&gt;
	CategoryEditor.OPEN = 1; // Open, but no input yet&lt;br /&gt;
	CategoryEditor.CHANGE_PENDING = 2; // Open, some input made&lt;br /&gt;
	CategoryEditor.CHANGED = 3;&lt;br /&gt;
	CategoryEditor.DELETED = 4;&lt;br /&gt;
&lt;br /&gt;
	// IE6 sometimes forgets to redraw the list when editors are opened or closed.&lt;br /&gt;
	// Adding/removing a dummy element helps, at least when opening editors.&lt;br /&gt;
	var dummyElement = make( '\xa0', true );&lt;br /&gt;
&lt;br /&gt;
	function forceRedraw() {&lt;br /&gt;
		if ( dummyElement.parentNode ) document.body.removeChild( dummyElement ); else document.body.appendChild( dummyElement );&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Event keyCodes that we handle in the text input field/suggestion list.&lt;br /&gt;
	var BS = 8,&lt;br /&gt;
		TAB = 9,&lt;br /&gt;
		RET = 13,&lt;br /&gt;
		ESC = 27,&lt;br /&gt;
		SPACE = 32,&lt;br /&gt;
		PGUP = 33,&lt;br /&gt;
		PGDOWN = 34,&lt;br /&gt;
		UP = 38,&lt;br /&gt;
		DOWN = 40,&lt;br /&gt;
		DEL = 46,&lt;br /&gt;
		IME = 229;&lt;br /&gt;
&lt;br /&gt;
	CategoryEditor.prototype = {&lt;br /&gt;
&lt;br /&gt;
		initialize: function ( line, span, after, key, is_hidden ) {&lt;br /&gt;
			// If a span is given, 'after' is the category title, otherwise it may be an element after which to&lt;br /&gt;
			// insert the new span. 'key' is likewise overloaded; if a span is given, it is the category key (if&lt;br /&gt;
			// known), otherwise it is a boolean indicating whether a bar shall be prepended.&lt;br /&gt;
			if ( !span ) {&lt;br /&gt;
				this.isAddCategory = true;&lt;br /&gt;
				// Create add span and append to catLinks&lt;br /&gt;
				this.originalCategory = '';&lt;br /&gt;
				this.originalKey = null;&lt;br /&gt;
				this.originalExists = false;&lt;br /&gt;
				if ( !newDOM ) {&lt;br /&gt;
					span = make( 'span' );&lt;br /&gt;
					span.className = 'noprint';&lt;br /&gt;
					if ( key ) {&lt;br /&gt;
						span.appendChild( make( ' | ', true ) );&lt;br /&gt;
						if ( after ) {&lt;br /&gt;
							after.parentNode.insertBefore( span, after.nextSibling );&lt;br /&gt;
							after = after.nextSibling;&lt;br /&gt;
						} else {&lt;br /&gt;
							line.appendChild( span );&lt;br /&gt;
						}&lt;br /&gt;
					} else if ( line.firstChild ) {&lt;br /&gt;
						span.appendChild( make( ' ', true ) );&lt;br /&gt;
						line.appendChild( span );&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				this.linkSpan = make( 'span' );&lt;br /&gt;
				this.linkSpan.className = 'noprint nopopups hotcatlink';&lt;br /&gt;
				var lk = make( 'a' );&lt;br /&gt;
				lk.href = '#catlinks';&lt;br /&gt;
				lk.onclick = this.open.bind( this );&lt;br /&gt;
				lk.appendChild( make( HC.links.add, true ) );&lt;br /&gt;
				lk.title = HC.tooltips.add;&lt;br /&gt;
				this.linkSpan.appendChild( lk );&lt;br /&gt;
				span = make( newDOM ? 'li' : 'span' );&lt;br /&gt;
				span.className = 'noprint';&lt;br /&gt;
				if ( is_rtl ) span.dir = 'rtl';&lt;br /&gt;
&lt;br /&gt;
				span.appendChild( this.linkSpan );&lt;br /&gt;
				if ( after ) after.parentNode.insertBefore( span, after.nextSibling ); else line.appendChild( span );&lt;br /&gt;
&lt;br /&gt;
				this.normalLinks = null;&lt;br /&gt;
				this.undelLink = null;&lt;br /&gt;
				this.catLink = null;&lt;br /&gt;
			} else {&lt;br /&gt;
				if ( is_rtl ) span.dir = 'rtl';&lt;br /&gt;
&lt;br /&gt;
				this.isAddCategory = false;&lt;br /&gt;
				this.catLink = span.firstChild;&lt;br /&gt;
				this.originalCategory = after;&lt;br /&gt;
				this.originalKey = ( key &amp;amp;&amp;amp; key.length &amp;gt; 1 ) ? key.substr( 1 ) : null; // &amp;gt; 1 because it includes the leading bar&lt;br /&gt;
				this.originalExists = !hasClass( this.catLink, 'new' );&lt;br /&gt;
				// Create change and del links&lt;br /&gt;
				this.makeLinkSpan();&lt;br /&gt;
				if ( !this.originalExists &amp;amp;&amp;amp; this.upDownLinks ) this.upDownLinks.style.display = 'none';&lt;br /&gt;
&lt;br /&gt;
				span.appendChild( this.linkSpan );&lt;br /&gt;
			}&lt;br /&gt;
			this.originalHidden = is_hidden;&lt;br /&gt;
			this.line = line;&lt;br /&gt;
			this.engine = HC.suggestions;&lt;br /&gt;
			this.span = span;&lt;br /&gt;
			this.currentCategory = this.originalCategory;&lt;br /&gt;
			this.currentExists = this.originalExists;&lt;br /&gt;
			this.currentHidden = this.originalHidden;&lt;br /&gt;
			this.currentKey = this.originalKey;&lt;br /&gt;
			this.state = CategoryEditor.UNCHANGED;&lt;br /&gt;
			this.lastSavedState = CategoryEditor.UNCHANGED;&lt;br /&gt;
			this.lastSavedCategory = this.originalCategory;&lt;br /&gt;
			this.lastSavedKey = this.originalKey;&lt;br /&gt;
			this.lastSavedExists = this.originalExists;&lt;br /&gt;
			this.lastSavedHidden = this.originalHidden;&lt;br /&gt;
			if ( this.catLink &amp;amp;&amp;amp; this.currentKey ) this.catLink.title = this.currentKey;&lt;br /&gt;
&lt;br /&gt;
			editors[ editors.length ] = this;&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		makeLinkSpan: function () {&lt;br /&gt;
			this.normalLinks = make( 'span' );&lt;br /&gt;
			var lk = null;&lt;br /&gt;
			if ( this.originalCategory &amp;amp;&amp;amp; this.originalCategory.length ) {&lt;br /&gt;
				lk = make( 'a' );&lt;br /&gt;
				lk.href = '#catlinks';&lt;br /&gt;
				lk.onclick = this.remove.bind( this );&lt;br /&gt;
				lk.appendChild( make( HC.links.remove, true ) );&lt;br /&gt;
				lk.title = HC.tooltips.remove;&lt;br /&gt;
				this.normalLinks.appendChild( make( ' ', true ) );&lt;br /&gt;
				this.normalLinks.appendChild( lk );&lt;br /&gt;
			}&lt;br /&gt;
			if ( !HC.template_categories[ this.originalCategory ] ) {&lt;br /&gt;
				lk = make( 'a' );&lt;br /&gt;
				lk.href = '#catlinks';&lt;br /&gt;
				lk.onclick = this.open.bind( this );&lt;br /&gt;
				lk.appendChild( make( HC.links.change, true ) );&lt;br /&gt;
				lk.title = HC.tooltips.change;&lt;br /&gt;
				this.normalLinks.appendChild( make( ' ', true ) );&lt;br /&gt;
				this.normalLinks.appendChild( lk );&lt;br /&gt;
				if ( !noSuggestions &amp;amp;&amp;amp; HC.use_up_down ) {&lt;br /&gt;
					this.upDownLinks = make( 'span' );&lt;br /&gt;
					lk = make( 'a' );&lt;br /&gt;
					lk.href = '#catlinks';&lt;br /&gt;
					lk.onclick = this.down.bind( this );&lt;br /&gt;
					lk.appendChild( make( HC.links.down, true ) );&lt;br /&gt;
					lk.title = HC.tooltips.down;&lt;br /&gt;
					this.upDownLinks.appendChild( make( ' ', true ) );&lt;br /&gt;
					this.upDownLinks.appendChild( lk );&lt;br /&gt;
					lk = make( 'a' );&lt;br /&gt;
					lk.href = '#catlinks';&lt;br /&gt;
					lk.onclick = this.up.bind( this );&lt;br /&gt;
					lk.appendChild( make( HC.links.up, true ) );&lt;br /&gt;
					lk.title = HC.tooltips.up;&lt;br /&gt;
					this.upDownLinks.appendChild( make( ' ', true ) );&lt;br /&gt;
					this.upDownLinks.appendChild( lk );&lt;br /&gt;
					this.normalLinks.appendChild( this.upDownLinks );&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			this.linkSpan = make( 'span' );&lt;br /&gt;
			this.linkSpan.className = 'noprint nopopups hotcatlink';&lt;br /&gt;
			this.linkSpan.appendChild( this.normalLinks );&lt;br /&gt;
			this.undelLink = make( 'span' );&lt;br /&gt;
			this.undelLink.className = 'nopopups hotcatlink';&lt;br /&gt;
			this.undelLink.style.display = 'none';&lt;br /&gt;
			lk = make( 'a' );&lt;br /&gt;
			lk.href = '#catlinks';&lt;br /&gt;
			lk.onclick = this.restore.bind( this );&lt;br /&gt;
			lk.appendChild( make( HC.links.restore, true ) );&lt;br /&gt;
			lk.title = HC.tooltips.restore;&lt;br /&gt;
			this.undelLink.appendChild( make( ' ', true ) );&lt;br /&gt;
			this.undelLink.appendChild( lk );&lt;br /&gt;
			this.linkSpan.appendChild( this.undelLink );&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		invokeSuggestions: function ( dont_autocomplete ) {&lt;br /&gt;
			if ( this.engine &amp;amp;&amp;amp; suggestionConfigs[ this.engine ] &amp;amp;&amp;amp; suggestionConfigs[ this.engine ].temp &amp;amp;&amp;amp; !dont_autocomplete ) this.engine = HC.suggestions; // Reset to a search upon input&lt;br /&gt;
&lt;br /&gt;
			this.state = CategoryEditor.CHANGE_PENDING;&lt;br /&gt;
			var self = this;&lt;br /&gt;
			window.setTimeout( function () {&lt;br /&gt;
				self.textchange( dont_autocomplete );&lt;br /&gt;
			}, HC.suggest_delay );&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		makeForm: function () {&lt;br /&gt;
			var form = make( 'form' );&lt;br /&gt;
			form.method = 'POST';&lt;br /&gt;
			form.onsubmit = this.accept.bind( this );&lt;br /&gt;
			this.form = form;&lt;br /&gt;
			var self = this;&lt;br /&gt;
			var text = make( 'input' );&lt;br /&gt;
			text.type = 'text';&lt;br /&gt;
			text.size = HC.editbox_width;&lt;br /&gt;
			if ( !noSuggestions ) {&lt;br /&gt;
				// Be careful here to handle IME input. This is browser/OS/IME dependent, but basically there are two mechanisms:&lt;br /&gt;
				// - Modern (DOM Level 3) browsers use compositionstart/compositionend events to signal composition; if the&lt;br /&gt;
				//   composition is not canceled, there'll be a textInput event following. During a composition key events are&lt;br /&gt;
				//   either all suppressed (FF/Gecko), or otherwise have keyDown === IME for all keys (Webkit).&lt;br /&gt;
				//   - Webkit sends a textInput followed by keyDown === IME and a keyUp with the key that ended composition.&lt;br /&gt;
				//   - Gecko doesn't send textInput but just a keyUp with the key that ended composition, without sending keyDown&lt;br /&gt;
				//     first. Gecko doesn't send any keydown while IME is active.&lt;br /&gt;
				// - Older browsers signal composition by keyDown === IME for the first and subsequent keys for a composition. The&lt;br /&gt;
				//   first keyDown !== IME is certainly after the end of the composition. Typically, composition end can also be&lt;br /&gt;
				//   detected by a keyDown IME with a keyUp of space, tab, escape, or return. (Example: IE8)&lt;br /&gt;
				text.onkeyup = function ( evt ) {&lt;br /&gt;
					evt = evt || window.event; // W3C, IE&lt;br /&gt;
					var key = evt.keyCode || 0;&lt;br /&gt;
					if ( self.ime &amp;amp;&amp;amp; self.lastKey === IME &amp;amp;&amp;amp; !self.usesComposition &amp;amp;&amp;amp; ( key === TAB || key === RET || key === ESC || key === SPACE ) ) self.ime = false;&lt;br /&gt;
&lt;br /&gt;
					if ( self.ime ) return true;&lt;br /&gt;
&lt;br /&gt;
					if ( key === UP || key === DOWN || key === PGUP || key === PGDOWN ) {&lt;br /&gt;
						// In case a browser doesn't generate keypress events for arrow keys...&lt;br /&gt;
						if ( self.keyCount === 0 ) return self.processKey( evt );&lt;br /&gt;
					} else {&lt;br /&gt;
						if ( key === ESC &amp;amp;&amp;amp; self.lastKey !== IME ) {&lt;br /&gt;
							if ( !self.resetKeySelection() ) {&lt;br /&gt;
								// No undo of key selection: treat ESC as &amp;quot;cancel&amp;quot;.&lt;br /&gt;
								self.cancel();&lt;br /&gt;
								return;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						// Also do this for ESC as a workaround for Firefox bug 524360&lt;br /&gt;
						// https://bugzilla.mozilla.org/show_bug.cgi?id=524360&lt;br /&gt;
						self.invokeSuggestions( key === BS || key === DEL || key === ESC );&lt;br /&gt;
					}&lt;br /&gt;
					return true;&lt;br /&gt;
				};&lt;br /&gt;
				text.onkeydown = function ( evt ) {&lt;br /&gt;
					evt = evt || window.event; // W3C, IE&lt;br /&gt;
					var key = evt.keyCode || 0;&lt;br /&gt;
					self.lastKey = key;&lt;br /&gt;
					self.keyCount = 0;&lt;br /&gt;
					// DOM Level &amp;lt; 3 IME input&lt;br /&gt;
					if ( !self.ime &amp;amp;&amp;amp; key === IME &amp;amp;&amp;amp; !self.usesComposition ) {&lt;br /&gt;
						// self.usesComposition catches browsers that may emit spurious keydown IME after a composition has ended&lt;br /&gt;
						self.ime = true;&lt;br /&gt;
					} else if ( self.ime &amp;amp;&amp;amp; key !== IME &amp;amp;&amp;amp; !( key &amp;gt;= 16 &amp;amp;&amp;amp; key &amp;lt;= 20 || key &amp;gt;= 91 &amp;amp;&amp;amp; key &amp;lt;= 93 || key === 144 ) ) {&lt;br /&gt;
						// Ignore control keys: ctrl, shift, alt, alt gr, caps lock, windows/apple cmd keys, num lock. Only the windows keys&lt;br /&gt;
						// terminate IME (apple cmd doesn't), but they also cause a blur, so it's OK to ignore them here.&lt;br /&gt;
						// Note: Safari 4 (530.17) propagates ESC out of an IME composition (observed at least on Win XP).&lt;br /&gt;
						self.ime = false;&lt;br /&gt;
					}&lt;br /&gt;
					if ( self.ime ) return true;&lt;br /&gt;
&lt;br /&gt;
					// Handle return explicitly, to override the default form submission to be able to check for ctrl&lt;br /&gt;
					if ( key === RET ) return self.accept( evt );&lt;br /&gt;
&lt;br /&gt;
					// Inhibit default behavior of ESC (revert to last real input in FF: we do that ourselves)&lt;br /&gt;
					return ( key === ESC ) ? evtKill( evt ) : true;&lt;br /&gt;
				};&lt;br /&gt;
				// And handle continued pressing of arrow keys&lt;br /&gt;
				text.onkeypress = function ( evt ) {&lt;br /&gt;
					self.keyCount++;&lt;br /&gt;
					return self.processKey( evt );&lt;br /&gt;
				};&lt;br /&gt;
				$( text ).on( 'focus', function () {&lt;br /&gt;
					makeActive( self );&lt;br /&gt;
				} );&lt;br /&gt;
				// On IE, blur events are asynchronous, and may thus arrive after the element has lost the focus. Since IE&lt;br /&gt;
				// can get the selection only while the element is active (has the focus), we may not always get the selection.&lt;br /&gt;
				// Therefore, use an IE-specific synchronous event on IE...&lt;br /&gt;
				// Don't test for text.selectionStart being defined; FF3.6.4 raises an exception when trying to access that&lt;br /&gt;
				// property while the element is not being displayed.&lt;br /&gt;
				$( text ).on(&lt;br /&gt;
					( text.onbeforedeactivate !== undefined &amp;amp;&amp;amp; text.createTextRange ) ? 'beforedeactivate' : 'blur',&lt;br /&gt;
					this.saveView.bind( this ) );&lt;br /&gt;
				// DOM Level 3 IME handling&lt;br /&gt;
				try {&lt;br /&gt;
					// Setting lastKey = IME provides a fake keyDown for Gecko's single keyUp after a cmposition. If we didn't do this,&lt;br /&gt;
					// cancelling a composition via ESC would also cancel and close the whole category input editor.&lt;br /&gt;
					$( text ).on( 'compositionstart', function () {&lt;br /&gt;
						self.lastKey = IME;&lt;br /&gt;
						self.usesComposition = true;&lt;br /&gt;
						self.ime = true;&lt;br /&gt;
					} );&lt;br /&gt;
					$( text ).on( 'compositionend', function () {&lt;br /&gt;
						self.lastKey = IME;&lt;br /&gt;
						self.usesComposition = true;&lt;br /&gt;
						self.ime = false;&lt;br /&gt;
					} );&lt;br /&gt;
					$( text ).on( 'textInput', function () {&lt;br /&gt;
						self.ime = false;&lt;br /&gt;
						self.invokeSuggestions( false );&lt;br /&gt;
					} );&lt;br /&gt;
				} catch ( any ) {&lt;br /&gt;
					// Just in case some browsers might produce exceptions with these DOM Level 3 events&lt;br /&gt;
				}&lt;br /&gt;
				$( text ).on( 'blur', function () {&lt;br /&gt;
					self.usesComposition = false;&lt;br /&gt;
					self.ime = false;&lt;br /&gt;
				} );&lt;br /&gt;
			}&lt;br /&gt;
			this.text = text;&lt;br /&gt;
&lt;br /&gt;
			this.icon = make( 'img' );&lt;br /&gt;
&lt;br /&gt;
			var list = null;&lt;br /&gt;
			if ( !noSuggestions ) {&lt;br /&gt;
				list = make( 'select' );&lt;br /&gt;
				list.onclick = function () {&lt;br /&gt;
					if ( self.highlightSuggestion( 0 ) ) self.textchange( false, true );&lt;br /&gt;
				};&lt;br /&gt;
				list.ondblclick = function ( e ) {&lt;br /&gt;
					if ( self.highlightSuggestion( 0 ) ) self.accept( e );&lt;br /&gt;
				};&lt;br /&gt;
				list.onchange = function () {&lt;br /&gt;
					self.highlightSuggestion( 0 );&lt;br /&gt;
					self.text.focus();&lt;br /&gt;
				};&lt;br /&gt;
				list.onkeyup = function ( evt ) {&lt;br /&gt;
					evt = evt || window.event; // W3C, IE&lt;br /&gt;
					if ( evt.keyCode === ESC ) {&lt;br /&gt;
						self.resetKeySelection();&lt;br /&gt;
						self.text.focus();&lt;br /&gt;
						window.setTimeout( function () {&lt;br /&gt;
							self.textchange( true );&lt;br /&gt;
						}, HC.suggest_delay );&lt;br /&gt;
					} else if ( evt.keyCode === RET ) {&lt;br /&gt;
						self.accept( evt );&lt;br /&gt;
					}&lt;br /&gt;
				};&lt;br /&gt;
				if ( !HC.fixed_search ) {&lt;br /&gt;
					var engineSelector = make( 'select' );&lt;br /&gt;
					for ( var key in suggestionConfigs ) {&lt;br /&gt;
						if ( suggestionConfigs[ key ].show ) {&lt;br /&gt;
							var opt = make( 'option' );&lt;br /&gt;
							opt.value = key;&lt;br /&gt;
							if ( key === this.engine ) opt.selected = true;&lt;br /&gt;
&lt;br /&gt;
							opt.appendChild( make( suggestionConfigs[ key ].name, true ) );&lt;br /&gt;
							engineSelector.appendChild( opt );&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
					engineSelector.onchange = function () {&lt;br /&gt;
						self.engine = self.engineSelector.options[ self.engineSelector.selectedIndex ].value;&lt;br /&gt;
						self.text.focus();&lt;br /&gt;
						self.textchange( true, true ); // Don't autocomplete, force re-display of list&lt;br /&gt;
					};&lt;br /&gt;
					this.engineSelector = engineSelector;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			this.list = list;&lt;br /&gt;
&lt;br /&gt;
			function button_label( id, defaultText ) {&lt;br /&gt;
				var label = null;&lt;br /&gt;
				if (&lt;br /&gt;
					onUpload &amp;amp;&amp;amp;&lt;br /&gt;
					window.UFUI !== undefined &amp;amp;&amp;amp;&lt;br /&gt;
					window.UIElements !== undefined &amp;amp;&amp;amp;&lt;br /&gt;
					UFUI.getLabel instanceof Function&lt;br /&gt;
				) {&lt;br /&gt;
					try {&lt;br /&gt;
						label = UFUI.getLabel( id, true );&lt;br /&gt;
						// Extract the plain text. IE doesn't know that Node.TEXT_NODE === 3&lt;br /&gt;
						while ( label &amp;amp;&amp;amp; label.nodeType !== 3 ) label = label.firstChild;&lt;br /&gt;
					} catch ( ex ) {&lt;br /&gt;
						label = null;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				if ( !label || !label.data ) return defaultText;&lt;br /&gt;
&lt;br /&gt;
				return label.data;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			// Do not use type 'submit'; we cannot detect modifier keys if we do&lt;br /&gt;
			var OK = make( 'input' );&lt;br /&gt;
			OK.type = 'button';&lt;br /&gt;
			OK.value = button_label( 'wpOkUploadLbl', HC.messages.ok );&lt;br /&gt;
			OK.onclick = this.accept.bind( this );&lt;br /&gt;
			this.ok = OK;&lt;br /&gt;
&lt;br /&gt;
			var cancel = make( 'input' );&lt;br /&gt;
			cancel.type = 'button';&lt;br /&gt;
			cancel.value = button_label( 'wpCancelUploadLbl', HC.messages.cancel );&lt;br /&gt;
			cancel.onclick = this.cancel.bind( this );&lt;br /&gt;
			this.cancelButton = cancel;&lt;br /&gt;
&lt;br /&gt;
			var span = make( 'span' );&lt;br /&gt;
			span.className = 'hotcatinput';&lt;br /&gt;
			span.style.position = 'relative';&lt;br /&gt;
			// FF3.6: add the input field first, then the two absolutely positioned elements. Otherwise, FF3.6 may leave the&lt;br /&gt;
			// suggestions and the selector at the right edge of the screen if display of the input field causes a re-layout&lt;br /&gt;
			// moving the form to the front of the next line.&lt;br /&gt;
			span.appendChild( text );&lt;br /&gt;
&lt;br /&gt;
			// IE8/IE9: put some text into this span (a0 is nbsp) and make sure it always stays on the&lt;br /&gt;
			// same line as the input field, otherwise, IE8/9 miscalculates the height of the span and&lt;br /&gt;
			// then the engine selector may overlap the input field.&lt;br /&gt;
			span.appendChild( make( '\xa0', true ) );&lt;br /&gt;
			span.style.whiteSpace = 'nowrap';&lt;br /&gt;
&lt;br /&gt;
			if ( list ) span.appendChild( list );&lt;br /&gt;
&lt;br /&gt;
			if ( this.engineSelector ) span.appendChild( this.engineSelector );&lt;br /&gt;
&lt;br /&gt;
			if ( !noSuggestions ) span.appendChild( this.icon );&lt;br /&gt;
&lt;br /&gt;
			span.appendChild( OK );&lt;br /&gt;
			span.appendChild( cancel );&lt;br /&gt;
			form.appendChild( span );&lt;br /&gt;
			form.style.display = 'none';&lt;br /&gt;
			this.span.appendChild( form );&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		display: function ( evt ) {&lt;br /&gt;
			if ( this.isAddCategory &amp;amp;&amp;amp; !onUpload ) {&lt;br /&gt;
				// eslint-disable-next-line no-new&lt;br /&gt;
				new CategoryEditor( this.line, null, this.span, true ); // Create a new one&lt;br /&gt;
			}&lt;br /&gt;
			if ( !commitButton &amp;amp;&amp;amp; !onUpload ) {&lt;br /&gt;
				for ( var i = 0; i &amp;lt; editors.length; i++ ) {&lt;br /&gt;
					if ( editors[ i ].state !== CategoryEditor.UNCHANGED ) {&lt;br /&gt;
						setMultiInput();&lt;br /&gt;
						break;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			if ( !this.form ) this.makeForm();&lt;br /&gt;
&lt;br /&gt;
			if ( this.list ) this.list.style.display = 'none';&lt;br /&gt;
&lt;br /&gt;
			if ( this.engineSelector ) this.engineSelector.style.display = 'none';&lt;br /&gt;
&lt;br /&gt;
			this.currentCategory = this.lastSavedCategory;&lt;br /&gt;
			this.currentExists = this.lastSavedExists;&lt;br /&gt;
			this.currentHidden = this.lastSavedHidden;&lt;br /&gt;
			this.currentKey = this.lastSavedKey;&lt;br /&gt;
			this.icon.src = armorUri( this.currentExists ? HC.existsYes : HC.existsNo );&lt;br /&gt;
			this.text.value = this.currentCategory + ( this.currentKey !== null ? '|' + this.currentKey : '' );&lt;br /&gt;
			this.originalState = this.state;&lt;br /&gt;
			this.lastInput = this.currentCategory;&lt;br /&gt;
			this.inputExists = this.currentExists;&lt;br /&gt;
			this.state = this.state === CategoryEditor.UNCHANGED ? CategoryEditor.OPEN : CategoryEditor.CHANGE_PENDING;&lt;br /&gt;
			this.lastSelection = {&lt;br /&gt;
				start: this.currentCategory.length,&lt;br /&gt;
				end: this.currentCategory.length&lt;br /&gt;
			};&lt;br /&gt;
			this.showsList = false;&lt;br /&gt;
			// Display the form&lt;br /&gt;
			if ( this.catLink ) this.catLink.style.display = 'none';&lt;br /&gt;
&lt;br /&gt;
			this.linkSpan.style.display = 'none';&lt;br /&gt;
			this.form.style.display = 'inline';&lt;br /&gt;
			this.ok.disabled = false;&lt;br /&gt;
			// Kill the event before focussing, otherwise IE will kill the onfocus event!&lt;br /&gt;
			var result = evtKill( evt );&lt;br /&gt;
			this.text.focus();&lt;br /&gt;
			this.text.readOnly = false;&lt;br /&gt;
			checkMultiInput();&lt;br /&gt;
			return result;&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		show: function ( evt, engine, readOnly ) {&lt;br /&gt;
			var result = this.display( evt );&lt;br /&gt;
			var v = this.lastSavedCategory;&lt;br /&gt;
			if ( !v.length ) return result;&lt;br /&gt;
&lt;br /&gt;
			this.text.readOnly = !!readOnly;&lt;br /&gt;
			this.engine = engine;&lt;br /&gt;
			this.textchange( false, true ); // do autocompletion, force display of suggestions&lt;br /&gt;
			forceRedraw();&lt;br /&gt;
			return result;&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		open: function ( evt ) {&lt;br /&gt;
			return this.show( evt, ( this.engine &amp;amp;&amp;amp; suggestionConfigs[ this.engine ].temp ) ? HC.suggestions : this.engine );&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		down: function ( evt ) {&lt;br /&gt;
			return this.show( evt, 'subcat', true );&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		up: function ( evt ) {&lt;br /&gt;
			return this.show( evt, 'parentcat' );&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		cancel: function () {&lt;br /&gt;
			if ( this.isAddCategory &amp;amp;&amp;amp; !onUpload ) {&lt;br /&gt;
				this.removeEditor(); // We added a new adder when opening&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			// Close, re-display link&lt;br /&gt;
			this.inactivate();&lt;br /&gt;
			this.form.style.display = 'none';&lt;br /&gt;
			if ( this.catLink ) this.catLink.style.display = '';&lt;br /&gt;
&lt;br /&gt;
			this.linkSpan.style.display = '';&lt;br /&gt;
			this.state = this.originalState;&lt;br /&gt;
			this.currentCategory = this.lastSavedCategory;&lt;br /&gt;
			this.currentKey = this.lastSavedKey;&lt;br /&gt;
			this.currentExists = this.lastSavedExists;&lt;br /&gt;
			this.currentHidden = this.lastSavedHidden;&lt;br /&gt;
			if ( this.catLink )&lt;br /&gt;
				if ( this.currentKey &amp;amp;&amp;amp; this.currentKey.length ) { this.catLink.title = this.currentKey; } else { this.catLink.title = ''; }&lt;br /&gt;
&lt;br /&gt;
			if ( this.state === CategoryEditor.UNCHANGED ) {&lt;br /&gt;
				if ( this.catLink ) this.catLink.style.backgroundColor = 'transparent';&lt;br /&gt;
			} else {&lt;br /&gt;
				if ( !onUpload ) {&lt;br /&gt;
					try {&lt;br /&gt;
						this.catLink.style.backgroundColor = HC.bg_changed;&lt;br /&gt;
					} catch ( ex ) {}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			checkMultiInput();&lt;br /&gt;
			forceRedraw();&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		removeEditor: function () {&lt;br /&gt;
			if ( !newDOM ) {&lt;br /&gt;
				var next = this.span.nextSibling;&lt;br /&gt;
				if ( next ) next.parentNode.removeChild( next );&lt;br /&gt;
			}&lt;br /&gt;
			this.span.parentNode.removeChild( this.span );&lt;br /&gt;
			for ( var i = 0; i &amp;lt; editors.length; i++ ) {&lt;br /&gt;
				if ( editors[ i ] === this ) {&lt;br /&gt;
					editors.splice( i, 1 );&lt;br /&gt;
					break;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			checkMultiInput();&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		rollback: function ( evt ) {&lt;br /&gt;
			this.undoLink.parentNode.removeChild( this.undoLink );&lt;br /&gt;
			this.undoLink = null;&lt;br /&gt;
			this.currentCategory = this.originalCategory;&lt;br /&gt;
			this.currentKey = this.originalKey;&lt;br /&gt;
			this.currentExists = this.originalExists;&lt;br /&gt;
			this.currentHidden = this.originalHidden;&lt;br /&gt;
			this.lastSavedCategory = this.originalCategory;&lt;br /&gt;
			this.lastSavedKey = this.originalKey;&lt;br /&gt;
			this.lastSavedExists = this.originalExists;&lt;br /&gt;
			this.lastSavedHidden = this.originalHidden;&lt;br /&gt;
			this.state = CategoryEditor.UNCHANGED;&lt;br /&gt;
			if ( !this.currentCategory || !this.currentCategory.length ) {&lt;br /&gt;
				// It was a newly added category. Remove the whole editor.&lt;br /&gt;
				this.removeEditor();&lt;br /&gt;
			} else {&lt;br /&gt;
				// Redisplay the link...&lt;br /&gt;
				this.catLink.removeChild( this.catLink.firstChild );&lt;br /&gt;
				this.catLink.appendChild( make( this.currentCategory, true ) );&lt;br /&gt;
				this.catLink.href = wikiPagePath( HC.category_canonical + ':' + this.currentCategory );&lt;br /&gt;
				this.catLink.title = this.currentKey || '';&lt;br /&gt;
				this.catLink.className = this.currentExists ? '' : 'new';&lt;br /&gt;
				this.catLink.style.backgroundColor = 'transparent';&lt;br /&gt;
				if ( this.upDownLinks ) this.upDownLinks.style.display = this.currentExists ? '' : 'none';&lt;br /&gt;
&lt;br /&gt;
				checkMultiInput();&lt;br /&gt;
			}&lt;br /&gt;
			return evtKill( evt );&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		inactivate: function () {&lt;br /&gt;
			if ( this.list ) this.list.style.display = 'none';&lt;br /&gt;
&lt;br /&gt;
			if ( this.engineSelector ) this.engineSelector.style.display = 'none';&lt;br /&gt;
&lt;br /&gt;
			this.is_active = false;&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		acceptCheck: function ( dontCheck ) {&lt;br /&gt;
			this.sanitizeInput();&lt;br /&gt;
			var value = this.text.value.split( '|' );&lt;br /&gt;
			var key = null;&lt;br /&gt;
			if ( value.length &amp;gt; 1 ) key = value[ 1 ];&lt;br /&gt;
&lt;br /&gt;
			var v = value[ 0 ].replace( /_/g, ' ' ).replace( /^\s+|\s+$/g, '' );&lt;br /&gt;
			if ( HC.capitalizePageNames ) v = capitalize( v );&lt;br /&gt;
&lt;br /&gt;
			this.lastInput = v;&lt;br /&gt;
			v = replaceShortcuts( v, HC.shortcuts );&lt;br /&gt;
			if ( !v.length ) {&lt;br /&gt;
				this.cancel();&lt;br /&gt;
				return false;&lt;br /&gt;
			}&lt;br /&gt;
			if ( !dontCheck &amp;amp;&amp;amp; (&lt;br /&gt;
				conf.wgNamespaceNumber === 14 &amp;amp;&amp;amp; v === conf.wgTitle || HC.blacklist &amp;amp;&amp;amp; HC.blacklist.test( v ) ) ) {&lt;br /&gt;
				this.cancel();&lt;br /&gt;
				return false;&lt;br /&gt;
			}&lt;br /&gt;
			this.currentCategory = v;&lt;br /&gt;
			this.currentKey = key;&lt;br /&gt;
			this.currentExists = this.inputExists;&lt;br /&gt;
			return true;&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		accept: function ( evt ) {&lt;br /&gt;
			// eslint-disable-next-line no-bitwise&lt;br /&gt;
			this.noCommit = ( evtKeys( evt ) &amp;amp; 1 ) !== 0;&lt;br /&gt;
			var result = evtKill( evt );&lt;br /&gt;
			if ( this.acceptCheck() ) {&lt;br /&gt;
				var toResolve = [ this ];&lt;br /&gt;
				var original = this.currentCategory;&lt;br /&gt;
				resolveMulti( toResolve, function ( resolved ) {&lt;br /&gt;
					if ( resolved[ 0 ].dab ) {&lt;br /&gt;
						showDab( resolved[ 0 ] );&lt;br /&gt;
					} else {&lt;br /&gt;
						if ( resolved[ 0 ].acceptCheck( true ) ) {&lt;br /&gt;
							resolved[ 0 ].commit(&lt;br /&gt;
								( resolved[ 0 ].currentCategory !== original ) ?&lt;br /&gt;
									HC.messages.cat_resolved.replace( /\$1/g, original ) :&lt;br /&gt;
									null );&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				} );&lt;br /&gt;
			}&lt;br /&gt;
			return result;&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		close: function () {&lt;br /&gt;
			if ( !this.catLink ) {&lt;br /&gt;
				// Create a catLink&lt;br /&gt;
				this.catLink = make( 'a' );&lt;br /&gt;
				this.catLink.appendChild( make( 'foo', true ) );&lt;br /&gt;
				this.catLink.style.display = 'none';&lt;br /&gt;
				this.span.insertBefore( this.catLink, this.span.firstChild.nextSibling );&lt;br /&gt;
			}&lt;br /&gt;
			this.catLink.removeChild( this.catLink.firstChild );&lt;br /&gt;
			this.catLink.appendChild( make( this.currentCategory, true ) );&lt;br /&gt;
			this.catLink.href = wikiPagePath( HC.category_canonical + ':' + this.currentCategory );&lt;br /&gt;
			this.catLink.className = this.currentExists ? '' : 'new';&lt;br /&gt;
			this.lastSavedCategory = this.currentCategory;&lt;br /&gt;
			this.lastSavedKey = this.currentKey;&lt;br /&gt;
			this.lastSavedExists = this.currentExists;&lt;br /&gt;
			this.lastSavedHidden = this.currentHidden;&lt;br /&gt;
			// Close form and redisplay category&lt;br /&gt;
			this.inactivate();&lt;br /&gt;
			this.form.style.display = 'none';&lt;br /&gt;
			this.catLink.title = this.currentKey || '';&lt;br /&gt;
			this.catLink.style.display = '';&lt;br /&gt;
			if ( this.isAddCategory ) {&lt;br /&gt;
				if ( onUpload ) {&lt;br /&gt;
					// eslint-disable-next-line no-new&lt;br /&gt;
					new CategoryEditor( this.line, null, this.span, true ); // Create a new one&lt;br /&gt;
				}&lt;br /&gt;
				this.isAddCategory = false;&lt;br /&gt;
				this.linkSpan.parentNode.removeChild( this.linkSpan );&lt;br /&gt;
				this.makeLinkSpan();&lt;br /&gt;
				this.span.appendChild( this.linkSpan );&lt;br /&gt;
			}&lt;br /&gt;
			if ( !this.undoLink ) {&lt;br /&gt;
				// Append an undo link.&lt;br /&gt;
				var span = make( 'span' );&lt;br /&gt;
				var lk = make( 'a' );&lt;br /&gt;
				lk.href = '#catlinks';&lt;br /&gt;
				lk.onclick = this.rollback.bind( this );&lt;br /&gt;
				lk.appendChild( make( HC.links.undo, true ) );&lt;br /&gt;
				lk.title = HC.tooltips.undo;&lt;br /&gt;
				span.appendChild( make( ' ', true ) );&lt;br /&gt;
				span.appendChild( lk );&lt;br /&gt;
				this.normalLinks.appendChild( span );&lt;br /&gt;
				this.undoLink = span;&lt;br /&gt;
				if ( !onUpload ) {&lt;br /&gt;
					try {&lt;br /&gt;
						this.catLink.style.backgroundColor = HC.bg_changed;&lt;br /&gt;
					} catch ( ex ) {}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			if ( this.upDownLinks ) this.upDownLinks.style.display = this.lastSavedExists ? '' : 'none';&lt;br /&gt;
&lt;br /&gt;
			this.linkSpan.style.display = '';&lt;br /&gt;
			this.state = CategoryEditor.CHANGED;&lt;br /&gt;
			checkMultiInput();&lt;br /&gt;
			forceRedraw();&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		commit: function () {&lt;br /&gt;
			// Check again to catch problem cases after redirect resolution&lt;br /&gt;
			if (&lt;br /&gt;
				(&lt;br /&gt;
					this.currentCategory === this.originalCategory &amp;amp;&amp;amp;&lt;br /&gt;
					(&lt;br /&gt;
						this.currentKey === this.originalKey ||&lt;br /&gt;
						this.currentKey === null &amp;amp;&amp;amp; !this.originalKey.length&lt;br /&gt;
					)&lt;br /&gt;
				) ||&lt;br /&gt;
				conf.wgNamespaceNumber === 14 &amp;amp;&amp;amp; this.currentCategory === conf.wgTitle ||&lt;br /&gt;
				HC.blacklist &amp;amp;&amp;amp; HC.blacklist.test( this.currentCategory )&lt;br /&gt;
			) {&lt;br /&gt;
				this.cancel();&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			if ( commitButton || onUpload ) {&lt;br /&gt;
				this.close();&lt;br /&gt;
			} else {&lt;br /&gt;
				this.close();&lt;br /&gt;
				var self = this;&lt;br /&gt;
				initiateEdit( function ( failure ) {&lt;br /&gt;
					performChanges( failure, self );&lt;br /&gt;
				}, function ( msg ) {&lt;br /&gt;
					alert( msg );&lt;br /&gt;
				} );&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		remove: function ( evt ) {&lt;br /&gt;
			// eslint-disable-next-line no-bitwise&lt;br /&gt;
			this.doRemove( evtKeys( evt ) &amp;amp; 1 );&lt;br /&gt;
			return evtKill( evt );&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		doRemove: function ( noCommit ) {&lt;br /&gt;
			if ( this.isAddCategory ) { // Empty input on adding a new category&lt;br /&gt;
				this.cancel();&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			if ( !commitButton &amp;amp;&amp;amp; !onUpload ) {&lt;br /&gt;
				for ( var i = 0; i &amp;lt; editors.length; i++ ) {&lt;br /&gt;
					if ( editors[ i ].state !== CategoryEditor.UNCHANGED ) {&lt;br /&gt;
						setMultiInput();&lt;br /&gt;
						break;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			if ( commitButton ) {&lt;br /&gt;
				this.catLink.title = '';&lt;br /&gt;
				this.catLink.style.cssText += '; text-decoration : line-through !important;';&lt;br /&gt;
				try {&lt;br /&gt;
					this.catLink.style.backgroundColor = HC.bg_changed;&lt;br /&gt;
				} catch ( ex ) {}&lt;br /&gt;
				this.originalState = this.state;&lt;br /&gt;
				this.state = CategoryEditor.DELETED;&lt;br /&gt;
				this.normalLinks.style.display = 'none';&lt;br /&gt;
				this.undelLink.style.display = '';&lt;br /&gt;
				checkMultiInput();&lt;br /&gt;
			} else {&lt;br /&gt;
				if ( onUpload ) {&lt;br /&gt;
					// Remove this editor completely&lt;br /&gt;
					this.removeEditor();&lt;br /&gt;
				} else {&lt;br /&gt;
					this.originalState = this.state;&lt;br /&gt;
					this.state = CategoryEditor.DELETED;&lt;br /&gt;
					this.noCommit = noCommit || HC.del_needs_diff;&lt;br /&gt;
					var self = this;&lt;br /&gt;
					initiateEdit(&lt;br /&gt;
						function ( failure ) {&lt;br /&gt;
							performChanges( failure, self );&lt;br /&gt;
						},&lt;br /&gt;
						function ( msg ) {&lt;br /&gt;
							self.state = self.originalState;&lt;br /&gt;
							alert( msg );&lt;br /&gt;
						} );&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		restore: function ( evt ) {&lt;br /&gt;
			// Can occur only if we do have a commit button and are not on the upload form&lt;br /&gt;
			this.catLink.title = this.currentKey || '';&lt;br /&gt;
			this.catLink.style.textDecoration = '';&lt;br /&gt;
			this.state = this.originalState;&lt;br /&gt;
			if ( this.state === CategoryEditor.UNCHANGED ) {&lt;br /&gt;
				this.catLink.style.backgroundColor = 'transparent';&lt;br /&gt;
			} else {&lt;br /&gt;
				try {&lt;br /&gt;
					this.catLink.style.backgroundColor = HC.bg_changed;&lt;br /&gt;
				} catch ( ex ) {}&lt;br /&gt;
			}&lt;br /&gt;
			this.normalLinks.style.display = '';&lt;br /&gt;
			this.undelLink.style.display = 'none';&lt;br /&gt;
			checkMultiInput();&lt;br /&gt;
			return evtKill( evt );&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		// Internal operations&lt;br /&gt;
&lt;br /&gt;
		selectEngine: function ( engineName ) {&lt;br /&gt;
			if ( !this.engineSelector ) return;&lt;br /&gt;
			for ( var i = 0; i &amp;lt; this.engineSelector.options.length; i++ ) this.engineSelector.options[ i ].selected = this.engineSelector.options[ i ].value === engineName;&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		sanitizeInput: function () {&lt;br /&gt;
			var v = this.text.value || '';&lt;br /&gt;
			v = v.replace( /^(\s|_)+/, '' ); // Trim leading blanks and underscores&lt;br /&gt;
			var re = new RegExp( '^(' + HC.category_regexp + '):' );&lt;br /&gt;
			if ( re.test( v ) ) v = v.substring( v.indexOf( ':' ) + 1 ).replace( /^(\s|_)+/, '' );&lt;br /&gt;
&lt;br /&gt;
			if ( HC.capitalizePageNames ) v = capitalize( v );&lt;br /&gt;
&lt;br /&gt;
			// Only update the input field if there is a difference. IE8 appears to reset the selection&lt;br /&gt;
			// and place the cursor at the front upon reset, which makes our autocompletetion become a&lt;br /&gt;
			// nuisance. FF and IE6 don't seem to have this problem.&lt;br /&gt;
			if ( this.text.value !== null &amp;amp;&amp;amp; this.text.value !== v ) this.text.value = v;&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		makeCall: function ( url, callbackObj, engine, queryKey, cleanKey ) {&lt;br /&gt;
			var cb = callbackObj,&lt;br /&gt;
				e = engine,&lt;br /&gt;
				v = queryKey,&lt;br /&gt;
				z = cleanKey,&lt;br /&gt;
				thisObj = this;&lt;br /&gt;
&lt;br /&gt;
			function done() {&lt;br /&gt;
				cb.callsMade++;&lt;br /&gt;
				if ( cb.callsMade === cb.nofCalls ) {&lt;br /&gt;
					if ( cb.exists ) cb.allTitles.exists = true;&lt;br /&gt;
&lt;br /&gt;
					if ( cb.normalized ) cb.allTitles.normalized = cb.normalized;&lt;br /&gt;
&lt;br /&gt;
					if ( !cb.dontCache &amp;amp;&amp;amp; !suggestionConfigs[ cb.engineName ].cache[ z ] ) suggestionConfigs[ cb.engineName ].cache[ z ] = cb.allTitles;&lt;br /&gt;
&lt;br /&gt;
					thisObj.text.readOnly = false;&lt;br /&gt;
					if ( !cb.cancelled ) thisObj.showSuggestions( cb.allTitles, cb.noCompletion, v, cb.engineName );&lt;br /&gt;
&lt;br /&gt;
					if ( cb === thisObj.callbackObj ) thisObj.callbackObj = null;&lt;br /&gt;
&lt;br /&gt;
					cb = undefined;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			$.getJSON( url, function ( json ) {&lt;br /&gt;
				var titles = e.handler( json, z );&lt;br /&gt;
				if ( titles &amp;amp;&amp;amp; titles.length ) {&lt;br /&gt;
					if ( cb.allTitles === null ) cb.allTitles = titles; else cb.allTitles = cb.allTitles.concat( titles );&lt;br /&gt;
					if ( titles.exists ) cb.exists = true;&lt;br /&gt;
					if ( titles.normalized ) cb.normalized = titles.normalized;&lt;br /&gt;
				}&lt;br /&gt;
				done();&lt;br /&gt;
			} ).fail( function ( req ) {&lt;br /&gt;
				if ( !req ) noSuggestions = true;&lt;br /&gt;
				cb.dontCache = true;&lt;br /&gt;
				done();&lt;br /&gt;
			} );&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		callbackObj: null,&lt;br /&gt;
&lt;br /&gt;
		textchange: function ( dont_autocomplete, force ) {&lt;br /&gt;
			// Hide all other lists&lt;br /&gt;
			makeActive( this );&lt;br /&gt;
			// Get input value, omit sort key, if any&lt;br /&gt;
			this.sanitizeInput();&lt;br /&gt;
			var v = this.text.value;&lt;br /&gt;
			// Disregard anything after a pipe.&lt;br /&gt;
			var pipe = v.indexOf( '|' );&lt;br /&gt;
			if ( pipe &amp;gt;= 0 ) {&lt;br /&gt;
				this.currentKey = v.substring( pipe + 1 );&lt;br /&gt;
				v = v.substring( 0, pipe );&lt;br /&gt;
			} else {&lt;br /&gt;
				this.currentKey = null;&lt;br /&gt;
			}&lt;br /&gt;
			if ( this.lastInput === v &amp;amp;&amp;amp; !force ) return; // No change&lt;br /&gt;
			if ( this.lastInput !== v ) checkMultiInput();&lt;br /&gt;
&lt;br /&gt;
			this.lastInput = v;&lt;br /&gt;
			this.lastRealInput = v;&lt;br /&gt;
&lt;br /&gt;
			// Mark blacklisted inputs.&lt;br /&gt;
			this.ok.disabled = v.length &amp;amp;&amp;amp; HC.blacklist &amp;amp;&amp;amp; HC.blacklist.test( v );&lt;br /&gt;
&lt;br /&gt;
			if ( noSuggestions ) {&lt;br /&gt;
			// No Ajax: just make sure the list is hidden&lt;br /&gt;
				if ( this.list ) this.list.style.display = 'none';&lt;br /&gt;
				if ( this.engineSelector ) this.engineSelector.style.display = 'none';&lt;br /&gt;
				if ( this.icon ) this.icon.style.display = 'none';&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			if ( !v.length ) {&lt;br /&gt;
				this.showSuggestions( [] );&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			var cleanKey = v.replace( /[\u200E\u200F\u202A-\u202E]/g, '' ).replace( wikiTextBlankRE, ' ' );&lt;br /&gt;
			cleanKey = replaceShortcuts( cleanKey, HC.shortcuts );&lt;br /&gt;
			cleanKey = cleanKey.replace( /^\s+|\s+$/g, '' );&lt;br /&gt;
			if ( !cleanKey.length ) {&lt;br /&gt;
				this.showSuggestions( [] );&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			if ( this.callbackObj ) this.callbackObj.cancelled = true;&lt;br /&gt;
&lt;br /&gt;
			var engineName = suggestionConfigs[ this.engine ] ? this.engine : 'combined';&lt;br /&gt;
&lt;br /&gt;
			dont_autocomplete = dont_autocomplete || suggestionConfigs[ engineName ].noCompletion;&lt;br /&gt;
			if ( suggestionConfigs[ engineName ].cache[ cleanKey ] ) {&lt;br /&gt;
				this.showSuggestions( suggestionConfigs[ engineName ].cache[ cleanKey ], dont_autocomplete, v, engineName );&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			var engines = suggestionConfigs[ engineName ].engines;&lt;br /&gt;
			this.callbackObj = {&lt;br /&gt;
				allTitles: null,&lt;br /&gt;
				callsMade: 0,&lt;br /&gt;
				nofCalls: engines.length,&lt;br /&gt;
				noCompletion: dont_autocomplete,&lt;br /&gt;
				engineName: engineName&lt;br /&gt;
			};&lt;br /&gt;
			this.makeCalls( engines, this.callbackObj, v, cleanKey );&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		makeCalls: function ( engines, cb, v, cleanKey ) {&lt;br /&gt;
			for ( var j = 0; j &amp;lt; engines.length; j++ ) {&lt;br /&gt;
				var engine = suggestionEngines[ engines[ j ] ];&lt;br /&gt;
				var url = conf.wgServer + conf.wgScriptPath + engine.uri.replace( /\$1/g, encodeURIComponent( cleanKey ) );&lt;br /&gt;
				this.makeCall( url, cb, engine, v, cleanKey );&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		showSuggestions: function ( titles, dontAutocomplete, queryKey, engineName ) {&lt;br /&gt;
			this.text.readOnly = false;&lt;br /&gt;
			this.dab = null;&lt;br /&gt;
			this.showsList = false;&lt;br /&gt;
			if ( !this.list ) return;&lt;br /&gt;
			if ( noSuggestions ) {&lt;br /&gt;
				if ( this.list ) this.list.style.display = 'none';&lt;br /&gt;
&lt;br /&gt;
				if ( this.engineSelector ) this.engineSelector.style.display = 'none';&lt;br /&gt;
&lt;br /&gt;
				if ( this.icon ) this.icon.style.display = 'none';&lt;br /&gt;
&lt;br /&gt;
				this.inputExists = true; // Default...&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			this.engineName = engineName;&lt;br /&gt;
			if ( engineName ) {&lt;br /&gt;
				if ( !this.engineSelector ) this.engineName = null;&lt;br /&gt;
			} else {&lt;br /&gt;
				if ( this.engineSelector ) this.engineSelector.style.display = 'none';&lt;br /&gt;
			}&lt;br /&gt;
			if ( queryKey ) {&lt;br /&gt;
				if ( this.lastInput.indexOf( queryKey ) ) return;&lt;br /&gt;
				if ( this.lastQuery &amp;amp;&amp;amp; this.lastInput.indexOf( this.lastQuery ) === 0 &amp;amp;&amp;amp; this.lastQuery.length &amp;gt; queryKey.length ) return;&lt;br /&gt;
			}&lt;br /&gt;
			this.lastQuery = queryKey;&lt;br /&gt;
&lt;br /&gt;
			// Get current input text&lt;br /&gt;
			var v = this.text.value.split( '|' );&lt;br /&gt;
			var key = v.length &amp;gt; 1 ? '|' + v[ 1 ] : '';&lt;br /&gt;
			v = ( HC.capitalizePageNames ? capitalize( v[ 0 ] ) : v[ 0 ] );&lt;br /&gt;
			var vNormalized = v;&lt;br /&gt;
			var knownToExist = titles &amp;amp;&amp;amp; titles.exists;&lt;br /&gt;
			var i;&lt;br /&gt;
			if ( titles ) {&lt;br /&gt;
				if ( titles.normalized &amp;amp;&amp;amp; v.indexOf( queryKey ) === 0 ) {&lt;br /&gt;
				// We got back a different normalization than what is in the input field&lt;br /&gt;
					vNormalized = titles.normalized + v.substring( queryKey.length );&lt;br /&gt;
				}&lt;br /&gt;
				var vLow = vNormalized.toLowerCase();&lt;br /&gt;
				// Strip blacklisted categories&lt;br /&gt;
				if ( HC.blacklist ) {&lt;br /&gt;
					for ( i = 0; i &amp;lt; titles.length; i++ ) {&lt;br /&gt;
						if ( HC.blacklist.test( titles[ i ] ) ) {&lt;br /&gt;
							titles.splice( i, 1 );&lt;br /&gt;
							i--;&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				titles.sort(&lt;br /&gt;
					function ( a, b ) {&lt;br /&gt;
						if ( a === b ) return 0;&lt;br /&gt;
&lt;br /&gt;
						if ( a.indexOf( b ) === 0 ) return 1;&lt;br /&gt;
						// a begins with b: a &amp;gt; b&lt;br /&gt;
						if ( b.indexOf( a ) === 0 ) return -1;&lt;br /&gt;
						// b begins with a: a &amp;lt; b&lt;br /&gt;
						// Opensearch may return stuff not beginning with the search prefix!&lt;br /&gt;
						var prefixMatchA = ( a.indexOf( vNormalized ) === 0 ? 1 : 0 );&lt;br /&gt;
						var prefixMatchB = ( b.indexOf( vNormalized ) === 0 ? 1 : 0 );&lt;br /&gt;
						if ( prefixMatchA !== prefixMatchB ) return prefixMatchB - prefixMatchA;&lt;br /&gt;
&lt;br /&gt;
						// Case-insensitive prefix match!&lt;br /&gt;
						var aLow = a.toLowerCase(),&lt;br /&gt;
							bLow = b.toLowerCase();&lt;br /&gt;
						prefixMatchA = ( aLow.indexOf( vLow ) === 0 ? 1 : 0 );&lt;br /&gt;
						prefixMatchB = ( bLow.indexOf( vLow ) === 0 ? 1 : 0 );&lt;br /&gt;
						if ( prefixMatchA !== prefixMatchB ) return prefixMatchB - prefixMatchA;&lt;br /&gt;
&lt;br /&gt;
						if ( a &amp;lt; b ) return -1;&lt;br /&gt;
&lt;br /&gt;
						if ( b &amp;lt; a ) return 1;&lt;br /&gt;
&lt;br /&gt;
						return 0;&lt;br /&gt;
					} );&lt;br /&gt;
				// Remove duplicates and self-references&lt;br /&gt;
				for ( i = 0; i &amp;lt; titles.length; i++ ) {&lt;br /&gt;
					if (&lt;br /&gt;
						i + 1 &amp;lt; titles.length &amp;amp;&amp;amp; titles[ i ] === titles[ i + 1 ] ||&lt;br /&gt;
						conf.wgNamespaceNumber === 14 &amp;amp;&amp;amp; titles[ i ] === conf.wgTitle&lt;br /&gt;
					) {&lt;br /&gt;
						titles.splice( i, 1 );&lt;br /&gt;
						i--;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			if ( !titles || !titles.length ) {&lt;br /&gt;
				if ( this.list ) this.list.style.display = 'none';&lt;br /&gt;
&lt;br /&gt;
				if ( this.engineSelector ) this.engineSelector.style.display = 'none';&lt;br /&gt;
&lt;br /&gt;
				if ( engineName &amp;amp;&amp;amp; suggestionConfigs[ engineName ] &amp;amp;&amp;amp; !suggestionConfigs[ engineName ].temp ) {&lt;br /&gt;
					if ( this.icon ) this.icon.src = armorUri( HC.existsNo );&lt;br /&gt;
&lt;br /&gt;
					this.inputExists = false;&lt;br /&gt;
				}&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			var firstTitle = titles[ 0 ];&lt;br /&gt;
			var completed = this.autoComplete( firstTitle, v, vNormalized, key, dontAutocomplete );&lt;br /&gt;
			var existing = completed || knownToExist || firstTitle === replaceShortcuts( v, HC.shortcuts );&lt;br /&gt;
			if ( engineName &amp;amp;&amp;amp; suggestionConfigs[ engineName ] &amp;amp;&amp;amp; !suggestionConfigs[ engineName ].temp ) {&lt;br /&gt;
				this.icon.src = armorUri( existing ? HC.existsYes : HC.existsNo );&lt;br /&gt;
				this.inputExists = existing;&lt;br /&gt;
			}&lt;br /&gt;
			if ( completed ) {&lt;br /&gt;
				this.lastInput = firstTitle;&lt;br /&gt;
				if ( titles.length === 1 ) {&lt;br /&gt;
					this.list.style.display = 'none';&lt;br /&gt;
					if ( this.engineSelector ) this.engineSelector.style.display = 'none';&lt;br /&gt;
&lt;br /&gt;
					return;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			// (Re-)fill the list&lt;br /&gt;
			while ( this.list.firstChild ) this.list.removeChild( this.list.firstChild );&lt;br /&gt;
&lt;br /&gt;
			for ( i = 0; i &amp;lt; titles.length; i++ ) {&lt;br /&gt;
				var opt = make( 'option' );&lt;br /&gt;
				opt.appendChild( make( titles[ i ], true ) );&lt;br /&gt;
				opt.selected = completed &amp;amp;&amp;amp; ( i === 0 );&lt;br /&gt;
				this.list.appendChild( opt );&lt;br /&gt;
			}&lt;br /&gt;
			this.displayList();&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		displayList: function () {&lt;br /&gt;
			this.showsList = true;&lt;br /&gt;
			if ( !this.is_active ) {&lt;br /&gt;
				this.list.style.display = 'none';&lt;br /&gt;
				if ( this.engineSelector ) this.engineSelector.style.display = 'none';&lt;br /&gt;
&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			var nofItems = ( this.list.options.length &amp;gt; HC.listSize ? HC.listSize : this.list.options.length );&lt;br /&gt;
			if ( nofItems &amp;lt;= 1 ) nofItems = 2;&lt;br /&gt;
&lt;br /&gt;
			this.list.size = nofItems;&lt;br /&gt;
			this.list.style.align = is_rtl ? 'right' : 'left';&lt;br /&gt;
			this.list.style.zIndex = 5;&lt;br /&gt;
			this.list.style.position = 'absolute';&lt;br /&gt;
			// Compute initial list position. First the height.&lt;br /&gt;
			var anchor = is_rtl ? 'right' : 'left';&lt;br /&gt;
			var listh = 0;&lt;br /&gt;
			if ( this.list.style.display === 'none' ) {&lt;br /&gt;
				// Off-screen display to get the height&lt;br /&gt;
				this.list.style.top = this.text.offsetTop + 'px';&lt;br /&gt;
				this.list.style[ anchor ] = '-10000px';&lt;br /&gt;
				this.list.style.display = '';&lt;br /&gt;
				listh = this.list.offsetHeight;&lt;br /&gt;
				this.list.style.display = 'none';&lt;br /&gt;
			} else {&lt;br /&gt;
				listh = this.list.offsetHeight;&lt;br /&gt;
			}&lt;br /&gt;
			// Approximate calculation of maximum list size&lt;br /&gt;
			var maxListHeight = listh;&lt;br /&gt;
			if ( nofItems &amp;lt; HC.listSize ) maxListHeight = ( listh / nofItems ) * HC.listSize;&lt;br /&gt;
&lt;br /&gt;
			function viewport( what ) {&lt;br /&gt;
				if ( is_webkit &amp;amp;&amp;amp; !document.evaluate ) {&lt;br /&gt;
				// Safari &amp;lt; 3.0&lt;br /&gt;
					return window[ 'inner' + what ];&lt;br /&gt;
				}&lt;br /&gt;
				var s = 'client' + what;&lt;br /&gt;
				if ( window.opera ) return document.body[ s ];&lt;br /&gt;
&lt;br /&gt;
				return ( document.documentElement ? document.documentElement[ s ] : 0 ) || document.body[ s ] || 0;&lt;br /&gt;
			}&lt;br /&gt;
			function scroll_offset( what ) {&lt;br /&gt;
				var s = 'scroll' + what;&lt;br /&gt;
				var result = ( document.documentElement ? document.documentElement[ s ] : 0 ) || document.body[ s ] || 0;&lt;br /&gt;
				if ( is_rtl &amp;amp;&amp;amp; what === 'Left' ) {&lt;br /&gt;
					// RTL inconsistencies.&lt;br /&gt;
					// FF: 0 at the far right, then increasingly negative values.&lt;br /&gt;
					// IE &amp;gt;= 8: 0 at the far right, then increasingly positive values.&lt;br /&gt;
					// Webkit: scrollWidth - clientWidth at the far right, then down to zero.&lt;br /&gt;
					// IE 7: like webkit; IE6: disabled in RTL anyway since too many problems.&lt;br /&gt;
					// Opera: don't know...&lt;br /&gt;
					if ( result &amp;lt; 0 ) result = -result;&lt;br /&gt;
&lt;br /&gt;
					if ( !is_webkit ) result = scroll_offset( 'Width' ) - viewport( 'Width' ) - result;&lt;br /&gt;
&lt;br /&gt;
					// Now all have webkit behavior, i.e. zero if at the leftmost edge.&lt;br /&gt;
				}&lt;br /&gt;
				return result;&lt;br /&gt;
			}&lt;br /&gt;
			function position( node ) {&lt;br /&gt;
				// Stripped-down simplified position function. It's good enough for our purposes.&lt;br /&gt;
				if ( node.getBoundingClientRect ) {&lt;br /&gt;
					var box = node.getBoundingClientRect();&lt;br /&gt;
					return {&lt;br /&gt;
						x: Math.round( box.left + scroll_offset( 'Left' ) ),&lt;br /&gt;
						y: Math.round( box.top + scroll_offset( 'Top' ) )&lt;br /&gt;
					};&lt;br /&gt;
				}&lt;br /&gt;
				var t = 0,&lt;br /&gt;
					l = 0;&lt;br /&gt;
				do {&lt;br /&gt;
					t += ( node.offsetTop || 0 );&lt;br /&gt;
					l += ( node.offsetLeft || 0 );&lt;br /&gt;
					node = node.offsetParent;&lt;br /&gt;
				} while ( node );&lt;br /&gt;
				return {&lt;br /&gt;
					x: l,&lt;br /&gt;
					y: t&lt;br /&gt;
				};&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			var textPos = position( this.text ),&lt;br /&gt;
				nl = 0,&lt;br /&gt;
				nt = 0,&lt;br /&gt;
				offset = 0,&lt;br /&gt;
				// Opera 9.5 somehow has offsetWidth = 0 here?? Use the next best value...&lt;br /&gt;
				textBoxWidth = this.text.offsetWidth || this.text.clientWidth;&lt;br /&gt;
			if ( this.engineName ) {&lt;br /&gt;
				this.engineSelector.style.zIndex = 5;&lt;br /&gt;
				this.engineSelector.style.position = 'absolute';&lt;br /&gt;
				this.engineSelector.style.width = textBoxWidth + 'px';&lt;br /&gt;
				// Figure out the height of this selector: display it off-screen, then hide it again.&lt;br /&gt;
				if ( this.engineSelector.style.display === 'none' ) {&lt;br /&gt;
					this.engineSelector.style[ anchor ] = '-10000px';&lt;br /&gt;
					this.engineSelector.style.top = '0';&lt;br /&gt;
					this.engineSelector.style.display = '';&lt;br /&gt;
					offset = this.engineSelector.offsetHeight;&lt;br /&gt;
					this.engineSelector.style.display = 'none';&lt;br /&gt;
				} else {&lt;br /&gt;
					offset = this.engineSelector.offsetHeight;&lt;br /&gt;
				}&lt;br /&gt;
				this.engineSelector.style[ anchor ] = nl + 'px';&lt;br /&gt;
			}&lt;br /&gt;
			if ( textPos.y &amp;lt; maxListHeight + offset + 1 ) {&lt;br /&gt;
			// The list might extend beyond the upper border of the page. Let's avoid that by placing it&lt;br /&gt;
			// below the input text field.&lt;br /&gt;
				nt = this.text.offsetHeight + offset + 1;&lt;br /&gt;
				if ( this.engineName ) this.engineSelector.style.top = this.text.offsetHeight + 'px';&lt;br /&gt;
			} else {&lt;br /&gt;
				nt = -listh - offset - 1;&lt;br /&gt;
				if ( this.engineName ) this.engineSelector.style.top = -( offset + 1 ) + 'px';&lt;br /&gt;
			}&lt;br /&gt;
			this.list.style.top = nt + 'px';&lt;br /&gt;
			this.list.style.width = ''; // No fixed width (yet)&lt;br /&gt;
			this.list.style[ anchor ] = nl + 'px';&lt;br /&gt;
			if ( this.engineName ) {&lt;br /&gt;
				this.selectEngine( this.engineName );&lt;br /&gt;
				this.engineSelector.style.display = '';&lt;br /&gt;
			}&lt;br /&gt;
			this.list.style.display = 'block';&lt;br /&gt;
			// Set the width of the list&lt;br /&gt;
			if ( this.list.offsetWidth &amp;lt; textBoxWidth ) {&lt;br /&gt;
				this.list.style.width = textBoxWidth + 'px';&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			// If the list is wider than the textbox: make sure it fits horizontally into the browser window&lt;br /&gt;
			var scroll = scroll_offset( 'Left' );&lt;br /&gt;
			var view_w = viewport( 'Width' );&lt;br /&gt;
			var w = this.list.offsetWidth;&lt;br /&gt;
			var l_pos = position( this.list );&lt;br /&gt;
			var left = l_pos.x;&lt;br /&gt;
			var right = left + w;&lt;br /&gt;
			if ( left &amp;lt; scroll || right &amp;gt; scroll + view_w ) {&lt;br /&gt;
				if ( w &amp;gt; view_w ) {&lt;br /&gt;
					w = view_w;&lt;br /&gt;
					this.list.style.width = w + 'px';&lt;br /&gt;
					if ( is_rtl ) left = right - w; else right = left + w;&lt;br /&gt;
				}&lt;br /&gt;
				var relative_offset = 0;&lt;br /&gt;
				if ( left &amp;lt; scroll ) relative_offset = scroll - left; else if ( right &amp;gt; scroll + view_w ) relative_offset = -( right - scroll - view_w );&lt;br /&gt;
&lt;br /&gt;
				if ( is_rtl ) relative_offset = -relative_offset;&lt;br /&gt;
&lt;br /&gt;
				if ( relative_offset ) this.list.style[ anchor ] = ( nl + relative_offset ) + 'px';&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		autoComplete: function ( newVal, actVal, normalizedActVal, key, dontModify ) {&lt;br /&gt;
			if ( newVal === actVal ) return true;&lt;br /&gt;
&lt;br /&gt;
			if ( dontModify || this.ime || !this.canSelect() ) return false;&lt;br /&gt;
&lt;br /&gt;
			// If we can't select properly or an IME composition is ongoing, autocompletion would be a major annoyance to the user.&lt;br /&gt;
			if ( newVal.indexOf( actVal ) ) {&lt;br /&gt;
				// Maybe it'll work with the normalized value (NFC)?&lt;br /&gt;
				if ( normalizedActVal &amp;amp;&amp;amp; newVal.indexOf( normalizedActVal ) === 0 ) {&lt;br /&gt;
					if ( this.lastRealInput === actVal ) this.lastRealInput = normalizedActVal;&lt;br /&gt;
&lt;br /&gt;
					actVal = normalizedActVal;&lt;br /&gt;
				} else {&lt;br /&gt;
					return false;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			// Actual input is a prefix of the new text. Fill in new text, selecting the newly added suffix&lt;br /&gt;
			// such that it can be easily removed by typing backspace if the suggestion is unwanted.&lt;br /&gt;
			this.text.focus();&lt;br /&gt;
			this.text.value = newVal + key;&lt;br /&gt;
			this.setSelection( actVal.length, newVal.length );&lt;br /&gt;
			return true;&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		canSelect: function () {&lt;br /&gt;
			return this.text.setSelectionRange ||&lt;br /&gt;
			this.text.createTextRange ||&lt;br /&gt;
			this.text.selectionStart !== undefined &amp;amp;&amp;amp;&lt;br /&gt;
			this.text.selectionEnd !== undefined;&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		setSelection: function ( from, to ) {&lt;br /&gt;
			// this.text must be focused (at least on IE)&lt;br /&gt;
			if ( !this.text.value ) return;&lt;br /&gt;
			if ( this.text.setSelectionRange ) { // e.g. khtml&lt;br /&gt;
				this.text.setSelectionRange( from, to );&lt;br /&gt;
			} else if ( this.text.selectionStart !== undefined ) {&lt;br /&gt;
				if ( from &amp;gt; this.text.selectionStart ) {&lt;br /&gt;
					this.text.selectionEnd = to;&lt;br /&gt;
					this.text.selectionStart = from;&lt;br /&gt;
				} else {&lt;br /&gt;
					this.text.selectionStart = from;&lt;br /&gt;
					this.text.selectionEnd = to;&lt;br /&gt;
				}&lt;br /&gt;
			} else if ( this.text.createTextRange ) { // IE&lt;br /&gt;
				var new_selection = this.text.createTextRange();&lt;br /&gt;
				new_selection.move( 'character', from );&lt;br /&gt;
				new_selection.moveEnd( 'character', to - from );&lt;br /&gt;
				new_selection.select();&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		getSelection: function () {&lt;br /&gt;
			var from = 0,&lt;br /&gt;
				to = 0;&lt;br /&gt;
			// this.text must be focused (at least on IE)&lt;br /&gt;
			if ( !this.text.value ) {&lt;br /&gt;
				// No text.&lt;br /&gt;
			} else if ( this.text.selectionStart !== undefined ) {&lt;br /&gt;
				from = this.text.selectionStart;&lt;br /&gt;
				to = this.text.selectionEnd;&lt;br /&gt;
			} else if ( document.selection &amp;amp;&amp;amp; document.selection.createRange ) { // IE&lt;br /&gt;
				var rng = document.selection.createRange().duplicate();&lt;br /&gt;
				if ( rng.parentElement() === this.text ) {&lt;br /&gt;
					try {&lt;br /&gt;
						var textRng = this.text.createTextRange();&lt;br /&gt;
						textRng.move( 'character', 0 );&lt;br /&gt;
						textRng.setEndPoint( 'EndToEnd', rng );&lt;br /&gt;
						// We're in a single-line input box: no need to care about IE's strange&lt;br /&gt;
						// handling of line ends&lt;br /&gt;
						to = textRng.text.length;&lt;br /&gt;
						textRng.setEndPoint( 'EndToStart', rng );&lt;br /&gt;
						from = textRng.text.length;&lt;br /&gt;
					} catch ( notFocused ) {&lt;br /&gt;
						from = this.text.value.length;&lt;br /&gt;
						to = from; // At end of text&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return {&lt;br /&gt;
				start: from,&lt;br /&gt;
				end: to&lt;br /&gt;
			};&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		saveView: function () {&lt;br /&gt;
			this.lastSelection = this.getSelection();&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		processKey: function ( evt ) {&lt;br /&gt;
			var dir = 0;&lt;br /&gt;
			switch ( this.lastKey ) {&lt;br /&gt;
				case UP:&lt;br /&gt;
					dir = -1;&lt;br /&gt;
					break;&lt;br /&gt;
				case DOWN:&lt;br /&gt;
					dir = 1;&lt;br /&gt;
					break;&lt;br /&gt;
				case PGUP:&lt;br /&gt;
					dir = -HC.listSize;&lt;br /&gt;
					break;&lt;br /&gt;
				case PGDOWN:&lt;br /&gt;
					dir = HC.listSize;&lt;br /&gt;
					break;&lt;br /&gt;
				case ESC: // Inhibit default behavior (revert to last real input in FF: we do that ourselves)&lt;br /&gt;
					return evtKill( evt );&lt;br /&gt;
			}&lt;br /&gt;
			if ( dir ) {&lt;br /&gt;
				if ( this.list.style.display !== 'none' ) {&lt;br /&gt;
				// List is visible, so there are suggestions&lt;br /&gt;
					this.highlightSuggestion( dir );&lt;br /&gt;
					// Kill the event, otherwise some browsers (e.g., Firefox) may additionally treat an up-arrow&lt;br /&gt;
					// as &amp;quot;place the text cursor at the front&amp;quot;, which we don't want here.&lt;br /&gt;
					return evtKill( evt );&lt;br /&gt;
				} else if (&lt;br /&gt;
					this.keyCount &amp;lt;= 1 &amp;amp;&amp;amp;&lt;br /&gt;
					( !this.callbackObj || this.callbackObj.callsMade === this.callbackObj.nofCalls )&lt;br /&gt;
				) {&lt;br /&gt;
					// If no suggestions displayed, get them, unless we're already getting them.&lt;br /&gt;
					this.textchange();&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return true;&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		highlightSuggestion: function ( dir ) {&lt;br /&gt;
			if ( noSuggestions || !this.list || this.list.style.display === 'none' ) return false;&lt;br /&gt;
&lt;br /&gt;
			var curr = this.list.selectedIndex;&lt;br /&gt;
			var tgt = -1;&lt;br /&gt;
			if ( dir === 0 ) {&lt;br /&gt;
				if ( curr &amp;lt; 0 || curr &amp;gt;= this.list.options.length ) return false;&lt;br /&gt;
&lt;br /&gt;
				tgt = curr;&lt;br /&gt;
			} else {&lt;br /&gt;
				tgt = curr &amp;lt; 0 ? 0 : curr + dir;&lt;br /&gt;
				tgt = tgt &amp;lt; 0 ? 0 : tgt;&lt;br /&gt;
				if ( tgt &amp;gt;= this.list.options.length ) tgt = this.list.options.length - 1;&lt;br /&gt;
			}&lt;br /&gt;
			if ( tgt !== curr || dir === 0 ) {&lt;br /&gt;
				if ( curr &amp;gt;= 0 &amp;amp;&amp;amp; curr &amp;lt; this.list.options.length &amp;amp;&amp;amp; dir !== 0 ) this.list.options[ curr ].selected = false;&lt;br /&gt;
&lt;br /&gt;
				this.list.options[ tgt ].selected = true;&lt;br /&gt;
				// Get current input text&lt;br /&gt;
				var v = this.text.value.split( '|' );&lt;br /&gt;
				var key = v.length &amp;gt; 1 ? '|' + v[ 1 ] : '';&lt;br /&gt;
				var completed = this.autoComplete( this.list.options[ tgt ].text, this.lastRealInput, null, key, false );&lt;br /&gt;
				if ( !completed || this.list.options[ tgt ].text === this.lastRealInput ) {&lt;br /&gt;
					this.text.value = this.list.options[ tgt ].text + key;&lt;br /&gt;
					if ( this.canSelect() ) this.setSelection( this.list.options[ tgt ].text.length, this.list.options[ tgt ].text.length );&lt;br /&gt;
				}&lt;br /&gt;
				this.lastInput = this.list.options[ tgt ].text;&lt;br /&gt;
				this.inputExists = true; // Might be wrong if from a dab list...&lt;br /&gt;
				if ( this.icon ) this.icon.src = armorUri( HC.existsYes );&lt;br /&gt;
&lt;br /&gt;
				this.state = CategoryEditor.CHANGE_PENDING;&lt;br /&gt;
			}&lt;br /&gt;
			return true;&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		resetKeySelection: function () {&lt;br /&gt;
			if ( noSuggestions || !this.list || this.list.style.display === 'none' ) return false;&lt;br /&gt;
&lt;br /&gt;
			var curr = this.list.selectedIndex;&lt;br /&gt;
			if ( curr &amp;gt;= 0 &amp;amp;&amp;amp; curr &amp;lt; this.list.options.length ) {&lt;br /&gt;
				this.list.options[ curr ].selected = false;&lt;br /&gt;
				// Get current input text&lt;br /&gt;
				var v = this.text.value.split( '|' );&lt;br /&gt;
				var key = v.length &amp;gt; 1 ? '|' + v[ 1 ] : '';&lt;br /&gt;
				// ESC is handled strangely by some browsers (e.g., FF); somehow it resets the input value before&lt;br /&gt;
				// our event handlers ever get a chance to run.&lt;br /&gt;
				var result = v[ 0 ] !== this.lastInput;&lt;br /&gt;
				if ( v[ 0 ] !== this.lastRealInput ) {&lt;br /&gt;
					this.text.value = this.lastRealInput + key;&lt;br /&gt;
					result = true;&lt;br /&gt;
				}&lt;br /&gt;
				this.lastInput = this.lastRealInput;&lt;br /&gt;
				return result;&lt;br /&gt;
			}&lt;br /&gt;
			return false;&lt;br /&gt;
		}&lt;br /&gt;
	}; // end CategoryEditor.prototype&lt;br /&gt;
&lt;br /&gt;
	function initialize() {&lt;br /&gt;
		// User configurations. Do this here, called from the onload handler, so that users can&lt;br /&gt;
		// override it easily in their own user script files by just declaring variables. JSconfig&lt;br /&gt;
		// is some feature used at Wikimedia Commons.&lt;br /&gt;
		var config = ( window.JSconfig !== undefined &amp;amp;&amp;amp; JSconfig.keys ) ? JSconfig.keys : {};&lt;br /&gt;
		HC.dont_add_to_watchlist = ( window.hotcat_dont_add_to_watchlist !== undefined ?&lt;br /&gt;
			!!window.hotcat_dont_add_to_watchlist :&lt;br /&gt;
			( config.HotCatDontAddToWatchlist !== undefined ? config.HotCatDontAddToWatchlist :&lt;br /&gt;
				HC.dont_add_to_watchlist ) );&lt;br /&gt;
		HC.no_autocommit = ( window.hotcat_no_autocommit !== undefined ?&lt;br /&gt;
			!!window.hotcat_no_autocommit : ( config.HotCatNoAutoCommit !== undefined ?&lt;br /&gt;
				config.HotCatNoAutoCommit :&lt;br /&gt;
				HC.no_autocommit ) );&lt;br /&gt;
		HC.del_needs_diff = ( window.hotcat_del_needs_diff !== undefined ?&lt;br /&gt;
			!!window.hotcat_del_needs_diff :&lt;br /&gt;
			( config.HotCatDelNeedsDiff !== undefined ?&lt;br /&gt;
				config.HotCatDelNeedsDiff :&lt;br /&gt;
				HC.del_needs_diff ) );&lt;br /&gt;
		HC.suggest_delay = window.hotcat_suggestion_delay || config.HotCatSuggestionDelay || HC.suggest_delay;&lt;br /&gt;
		HC.editbox_width = window.hotcat_editbox_width || config.HotCatEditBoxWidth || HC.editbox_width;&lt;br /&gt;
		HC.suggestions = window.hotcat_suggestions || config.HotCatSuggestions || HC.suggestions;&lt;br /&gt;
		if ( typeof HC.suggestions !== 'string' || !suggestionConfigs[ HC.suggestions ] ) HC.suggestions = 'combined';&lt;br /&gt;
&lt;br /&gt;
		HC.fixed_search = ( window.hotcat_suggestions_fixed !== undefined ?&lt;br /&gt;
			!!window.hotcat_suggestions_fixed : ( config.HotCatFixedSuggestions !== undefined ?&lt;br /&gt;
				config.HotCatFixedSuggestions : HC.fixed_search ) );&lt;br /&gt;
		HC.single_minor = ( window.hotcat_single_changes_are_minor !== undefined ?&lt;br /&gt;
			!!window.hotcat_single_changes_are_minor :&lt;br /&gt;
			( config.HotCatMinorSingleChanges !== undefined ?&lt;br /&gt;
				config.HotCatMinorSingleChanges :&lt;br /&gt;
				HC.single_minor ) );&lt;br /&gt;
		HC.bg_changed = window.hotcat_changed_background || config.HotCatChangedBackground || HC.bg_changed;&lt;br /&gt;
		HC.use_up_down = ( window.hotcat_use_category_links !== undefined ?&lt;br /&gt;
			!!window.hotcat_use_category_links :&lt;br /&gt;
			( config.HotCatUseCategoryLinks !== undefined ?&lt;br /&gt;
				config.HotCatUseCategoryLinks :&lt;br /&gt;
				HC.use_up_down ) );&lt;br /&gt;
		HC.listSize = window.hotcat_listSize || config.HotCatListSize || HC.listSize;&lt;br /&gt;
		if ( conf.wgDBname !== 'commonswiki' ) HC.changeTag = config.HotCatChangeTag || '';&lt;br /&gt;
&lt;br /&gt;
		// The next whole shebang is needed, because manual tags get not submitted except of save&lt;br /&gt;
		if ( HC.changeTag ) {&lt;br /&gt;
			var eForm = document.editform,&lt;br /&gt;
				catRegExp = new RegExp( '^\\[\\[(' + HC.category_regexp + '):' ),&lt;br /&gt;
				oldTxt;&lt;br /&gt;
			// Returns true if minor change&lt;br /&gt;
			var isMinorChange = function () {&lt;br /&gt;
				var newTxt = eForm.wpTextbox1;&lt;br /&gt;
				if ( !newTxt ) return;&lt;br /&gt;
				newTxt = newTxt.value;&lt;br /&gt;
				var oldLines = oldTxt.match( /^.*$/gm ),&lt;br /&gt;
					newLines = newTxt.match( /^.*$/gm ),&lt;br /&gt;
					cArr; // changes&lt;br /&gt;
				var except = function ( aArr, bArr ) {&lt;br /&gt;
					var result = [],&lt;br /&gt;
						lArr, // larger&lt;br /&gt;
						sArr; // smaller&lt;br /&gt;
					if ( aArr.length &amp;lt; bArr.length ) {&lt;br /&gt;
						lArr = bArr;&lt;br /&gt;
						sArr = aArr;&lt;br /&gt;
					} else {&lt;br /&gt;
						lArr = aArr;&lt;br /&gt;
						sArr = bArr;&lt;br /&gt;
					}&lt;br /&gt;
					for ( var i = 0; i &amp;lt; lArr.length; i++ ) {&lt;br /&gt;
						var item = lArr[ i ];&lt;br /&gt;
						var ind = $.inArray( item, sArr );&lt;br /&gt;
						if ( ind === -1 ) result.push( item );&lt;br /&gt;
						else sArr.splice( ind, 1 ); // don't check this item again&lt;br /&gt;
					}&lt;br /&gt;
					return result.concat( sArr );&lt;br /&gt;
				};&lt;br /&gt;
				cArr = except( oldLines, newLines );&lt;br /&gt;
				if ( cArr.length ) {&lt;br /&gt;
					cArr = $.grep( cArr, function ( c ) {&lt;br /&gt;
						c = $.trim( c );&lt;br /&gt;
						return ( c &amp;amp;&amp;amp; !catRegExp.test( c ) );&lt;br /&gt;
					} );&lt;br /&gt;
				}&lt;br /&gt;
				if ( !cArr.length ) {&lt;br /&gt;
					oldTxt = newTxt;&lt;br /&gt;
					return true;&lt;br /&gt;
				}&lt;br /&gt;
			};&lt;br /&gt;
&lt;br /&gt;
			if ( conf.wgAction === 'submit' &amp;amp;&amp;amp; conf.wgArticleId &amp;amp;&amp;amp; eForm &amp;amp;&amp;amp; eForm.wpSummary &amp;amp;&amp;amp; document.getElementById( 'wikiDiff' ) ) {&lt;br /&gt;
				var sum = eForm.wpSummary,&lt;br /&gt;
					sumA = eForm.wpAutoSummary;&lt;br /&gt;
				if ( sum.value &amp;amp;&amp;amp; sumA.value === HC.changeTag ) { // HotCat diff&lt;br /&gt;
				// MD5 hash of the empty string, as HotCat edit is based on empty sum&lt;br /&gt;
					sumA.value = sumA.value.replace( HC.changeTag, 'd41d8cd98f00b204e9800998ecf8427e' );&lt;br /&gt;
					// Attr creation and event handling is not same in all (old) browsers so use $&lt;br /&gt;
					var $ct = $( '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;wpChangeTags&amp;quot;&amp;gt;' ).val( HC.changeTag );&lt;br /&gt;
					$( eForm ).append( $ct );&lt;br /&gt;
					oldTxt = eForm.wpTextbox1.value;&lt;br /&gt;
					$( '#wpSave' ).one( 'click', function () {&lt;br /&gt;
						if ( $ct.val() )&lt;br /&gt;
							sum.value = sum.value.replace( ( HC.messages.using || HC.messages.prefix ), '' );&lt;br /&gt;
&lt;br /&gt;
					} );&lt;br /&gt;
					var removeChangeTag = function () {&lt;br /&gt;
						$( eForm.wpTextbox1 ).add( sum ).one( 'input', function () {&lt;br /&gt;
							window.setTimeout( function () {&lt;br /&gt;
								if ( !isMinorChange() ) $ct.val( '' );&lt;br /&gt;
								else removeChangeTag();&lt;br /&gt;
							}, 500 );&lt;br /&gt;
						} );&lt;br /&gt;
					};&lt;br /&gt;
					removeChangeTag();&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		// Numeric input, make sure we have a numeric value&lt;br /&gt;
		HC.listSize = parseInt( HC.listSize, 10 );&lt;br /&gt;
		if ( isNaN( HC.listSize ) || HC.listSize &amp;lt; 5 ) HC.listSize = 5;&lt;br /&gt;
&lt;br /&gt;
		HC.listSize = Math.min( HC.listSize, 15 );&lt;br /&gt;
&lt;br /&gt;
		// Localize search engine names&lt;br /&gt;
		if ( HC.engine_names ) {&lt;br /&gt;
			for ( var key in HC.engine_names )&lt;br /&gt;
				if ( suggestionConfigs[ key ] &amp;amp;&amp;amp; HC.engine_names[ key ] ) suggestionConfigs[ key ].name = HC.engine_names[ key ];&lt;br /&gt;
&lt;br /&gt;
		}&lt;br /&gt;
		// Catch both native RTL and &amp;quot;faked&amp;quot; RTL through [[MediaWiki:Rtl.js]]&lt;br /&gt;
		is_rtl = hasClass( document.body, 'rtl' );&lt;br /&gt;
		if ( !is_rtl ) {&lt;br /&gt;
			if ( document.defaultView &amp;amp;&amp;amp; document.defaultView.getComputedStyle ) { // Gecko etc.&lt;br /&gt;
				is_rtl = document.defaultView.getComputedStyle( document.body, null ).getPropertyValue( 'direction' );&lt;br /&gt;
			} else if ( document.body.currentStyle ) { // IE, has subtle differences to getComputedStyle&lt;br /&gt;
				is_rtl = document.body.currentStyle.direction;&lt;br /&gt;
			} else { // Not exactly right, but best effort&lt;br /&gt;
				is_rtl = document.body.style.direction;&lt;br /&gt;
			}&lt;br /&gt;
			is_rtl = ( is_rtl === 'rtl' );&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function can_edit() {&lt;br /&gt;
		var container = null;&lt;br /&gt;
		switch ( mw.config.get( 'skin' ) ) {&lt;br /&gt;
			case 'cologneblue':&lt;br /&gt;
				container = document.getElementById( 'quickbar' );&lt;br /&gt;
			/* fall through */&lt;br /&gt;
			case 'standard':&lt;br /&gt;
			case 'nostalgia':&lt;br /&gt;
				if ( !container ) container = document.getElementById( 'topbar' );&lt;br /&gt;
				var lks = container.getElementsByTagName( 'a' );&lt;br /&gt;
				for ( var i = 0; i &amp;lt; lks.length; i++ ) {&lt;br /&gt;
					if (&lt;br /&gt;
						param( 'title', lks[ i ].href ) === conf.wgPageName &amp;amp;&amp;amp;&lt;br /&gt;
						param( 'action', lks[ i ].href ) === 'edit'&lt;br /&gt;
					) {&lt;br /&gt;
						return true;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				return false;&lt;br /&gt;
			default:&lt;br /&gt;
				// all modern skins:&lt;br /&gt;
				return document.getElementById( 'ca-edit' ) !== null;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Legacy stuff&lt;br /&gt;
	function closeForm() {&lt;br /&gt;
		// Close all open editors without redirect resolution and other asynchronous stuff.&lt;br /&gt;
		for ( var i = 0; i &amp;lt; editors.length; i++ ) {&lt;br /&gt;
			var edit = editors[ i ];&lt;br /&gt;
			if ( edit.state === CategoryEditor.OPEN ) {&lt;br /&gt;
				edit.cancel();&lt;br /&gt;
			} else if ( edit.state === CategoryEditor.CHANGE_PENDING ) {&lt;br /&gt;
				edit.sanitizeInput();&lt;br /&gt;
				var value = edit.text.value.split( '|' );&lt;br /&gt;
				var key = null;&lt;br /&gt;
				if ( value.length &amp;gt; 1 ) key = value[ 1 ];&lt;br /&gt;
				var v = value[ 0 ].replace( /_/g, ' ' ).replace( /^\s+|\s+$/g, '' );&lt;br /&gt;
				if ( !v.length ) {&lt;br /&gt;
					edit.cancel();&lt;br /&gt;
				} else {&lt;br /&gt;
					edit.currentCategory = v;&lt;br /&gt;
					edit.currentKey = key;&lt;br /&gt;
					edit.currentExists = this.inputExists;&lt;br /&gt;
					edit.close();&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function setup_upload() {&lt;br /&gt;
		onUpload = true;&lt;br /&gt;
		// Add an empty category bar at the end of the table containing the description, and change the onsubmit handler.&lt;br /&gt;
		var ip = document.getElementById( 'mw-htmlform-description' ) || document.getElementById( 'wpDestFile' );&lt;br /&gt;
		if ( !ip ) {&lt;br /&gt;
			ip = document.getElementById( 'wpDestFile' );&lt;br /&gt;
			while ( ip &amp;amp;&amp;amp; ip.nodeName.toLowerCase() !== 'table' ) ip = ip.parentNode;&lt;br /&gt;
		}&lt;br /&gt;
		if ( !ip ) return;&lt;br /&gt;
		var reupload = document.getElementById( 'wpForReUpload' );&lt;br /&gt;
		var destFile = document.getElementById( 'wpDestFile' );&lt;br /&gt;
		if (&lt;br /&gt;
			( reupload &amp;amp;&amp;amp; !!reupload.value ) ||&lt;br /&gt;
			( destFile &amp;amp;&amp;amp; ( destFile.disabled || destFile.readOnly ) )&lt;br /&gt;
		) {&lt;br /&gt;
			return; // re-upload form...&lt;br /&gt;
		}&lt;br /&gt;
		// Insert a table row with two fields (label and empty category bar)&lt;br /&gt;
		var labelCell = make( 'td' );&lt;br /&gt;
		var lineCell = make( 'td' );&lt;br /&gt;
		// Create the category line&lt;br /&gt;
		catLine = make( 'div' );&lt;br /&gt;
		catLine.className = 'catlinks';&lt;br /&gt;
		catLine.id = 'catlinks';&lt;br /&gt;
		catLine.style.textAlign = is_rtl ? 'right' : 'left';&lt;br /&gt;
		// We'll be inside a table row. Make sure that we don't have margins or strange borders.&lt;br /&gt;
		catLine.style.margin = '0';&lt;br /&gt;
		catLine.style.border = 'none';&lt;br /&gt;
		lineCell.appendChild( catLine );&lt;br /&gt;
		// Create the label&lt;br /&gt;
		var label = null;&lt;br /&gt;
		if ( window.UFUI &amp;amp;&amp;amp; window.UIElements &amp;amp;&amp;amp; UFUI.getLabel instanceof Function ) {&lt;br /&gt;
			try {&lt;br /&gt;
				label = UFUI.getLabel( 'wpCategoriesUploadLbl' );&lt;br /&gt;
			} catch ( ex ) {&lt;br /&gt;
				label = null;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		if ( !label ) {&lt;br /&gt;
			labelCell.id = 'hotcatLabel';&lt;br /&gt;
			labelCell.appendChild( make( HC.categories, true ) );&lt;br /&gt;
		} else {&lt;br /&gt;
			labelCell.id = 'hotcatLabelTranslated';&lt;br /&gt;
			labelCell.appendChild( label );&lt;br /&gt;
		}&lt;br /&gt;
		labelCell.className = 'mw-label';&lt;br /&gt;
		labelCell.style.textAlign = 'right';&lt;br /&gt;
		labelCell.style.verticalAlign = 'middle';&lt;br /&gt;
		// Change the onsubmit handler&lt;br /&gt;
		var form = document.getElementById( 'upload' ) || document.getElementById( 'mw-upload-form' );&lt;br /&gt;
		if ( form ) {&lt;br /&gt;
			var newRow = ip.insertRow( -1 );&lt;br /&gt;
			newRow.appendChild( labelCell );&lt;br /&gt;
			newRow.appendChild( lineCell );&lt;br /&gt;
			form.onsubmit = ( function ( oldSubmit ) {&lt;br /&gt;
				return function () {&lt;br /&gt;
					var do_submit = true;&lt;br /&gt;
					if ( oldSubmit ) {&lt;br /&gt;
						if ( typeof oldSubmit === 'string' ) {&lt;br /&gt;
						// eslint-disable-next-line no-eval&lt;br /&gt;
							do_submit = eval( oldSubmit );&lt;br /&gt;
						} else if ( oldSubmit instanceof Function ) {&lt;br /&gt;
							do_submit = oldSubmit.apply( form, arguments );&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
					if ( !do_submit ) return false;&lt;br /&gt;
					closeForm();&lt;br /&gt;
					// Copy the categories&lt;br /&gt;
					var eb = document.getElementById( 'wpUploadDescription' ) || document.getElementById( 'wpDesc' );&lt;br /&gt;
					var addedOne = false;&lt;br /&gt;
					for ( var i = 0; i &amp;lt; editors.length; i++ ) {&lt;br /&gt;
						var t = editors[ i ].currentCategory;&lt;br /&gt;
						if ( !t ) continue;&lt;br /&gt;
						var key = editors[ i ].currentKey;&lt;br /&gt;
						var new_cat = '[[' + HC.category_canonical + ':' + t + ( key ? '|' + key : '' ) + ']]';&lt;br /&gt;
						// Only add if not already present&lt;br /&gt;
						var cleanedText = eb.value&lt;br /&gt;
							.replace( /&amp;lt;!--(\s|\S)*?--&amp;gt;/g, '' )&lt;br /&gt;
							.replace( /&amp;lt;nowiki&amp;gt;(\s|\S)*?&amp;lt;\/nowiki&amp;gt;/g, '' );&lt;br /&gt;
						if ( !find_category( cleanedText, t, true ) ) {&lt;br /&gt;
							eb.value += '\n' + new_cat;&lt;br /&gt;
							addedOne = true;&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
					if ( addedOne ) {&lt;br /&gt;
					// Remove &amp;quot;subst:unc&amp;quot; added by Flinfo if it didn't find categories&lt;br /&gt;
						eb.value = eb.value.replace( /\{\{subst:unc\}\}/g, '' );&lt;br /&gt;
					}&lt;br /&gt;
					return true;&lt;br /&gt;
				};&lt;br /&gt;
			}( form.onsubmit ) );&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var cleanedText = null;&lt;br /&gt;
&lt;br /&gt;
	function isOnPage( span ) {&lt;br /&gt;
		if ( span.firstChild.nodeType !== Node.ELEMENT_NODE ) return null;&lt;br /&gt;
&lt;br /&gt;
		var catTitle = title( span.firstChild.getAttribute( 'href' ) );&lt;br /&gt;
		if ( !catTitle ) return null;&lt;br /&gt;
&lt;br /&gt;
		catTitle = catTitle.substr( catTitle.indexOf( ':' ) + 1 ).replace( /_/g, ' ' );&lt;br /&gt;
		if ( HC.blacklist &amp;amp;&amp;amp; HC.blacklist.test( catTitle ) ) return null;&lt;br /&gt;
&lt;br /&gt;
		var result = {&lt;br /&gt;
			title: catTitle,&lt;br /&gt;
			match: [ '', '', '' ]&lt;br /&gt;
		};&lt;br /&gt;
		if ( pageText === null ) return result;&lt;br /&gt;
&lt;br /&gt;
		if ( cleanedText === null ) {&lt;br /&gt;
			cleanedText = pageText&lt;br /&gt;
				.replace( /&amp;lt;!--(\s|\S)*?--&amp;gt;/g, '' )&lt;br /&gt;
				.replace( /&amp;lt;nowiki&amp;gt;(\s|\S)*?&amp;lt;\/nowiki&amp;gt;/g, '' );&lt;br /&gt;
		}&lt;br /&gt;
		result.match = find_category( cleanedText, catTitle, true );&lt;br /&gt;
		return result;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var initialized = false;&lt;br /&gt;
	var setupTimeout = null;&lt;br /&gt;
&lt;br /&gt;
	function findByClass( scope, tag, className ) {&lt;br /&gt;
		var result = $( scope ).find( tag + '.' + className );&lt;br /&gt;
		return ( result &amp;amp;&amp;amp; result.length ) ? result[ 0 ] : null;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function setup( additionalWork ) {&lt;br /&gt;
		if ( initialized ) return;&lt;br /&gt;
		initialized = true;&lt;br /&gt;
		if ( setupTimeout ) {&lt;br /&gt;
			window.clearTimeout( setupTimeout );&lt;br /&gt;
			setupTimeout = null;&lt;br /&gt;
		}&lt;br /&gt;
		// Find the category bar, or create an empty one if there isn't one. Then add -/+- links after&lt;br /&gt;
		// each category, and add the + link.&lt;br /&gt;
		catLine =&lt;br /&gt;
			// Special:Upload&lt;br /&gt;
			catLine ||&lt;br /&gt;
			document.getElementById( 'mw-normal-catlinks' );&lt;br /&gt;
		var hiddenCats = document.getElementById( 'mw-hidden-catlinks' );&lt;br /&gt;
		if ( !catLine ) {&lt;br /&gt;
			var footer = null;&lt;br /&gt;
			if ( !hiddenCats ) {&lt;br /&gt;
				footer = findByClass( document, 'div', 'printfooter' );&lt;br /&gt;
				if ( !footer ) return; // Don't know where to insert the category line&lt;br /&gt;
			}&lt;br /&gt;
			catLine = make( 'div' );&lt;br /&gt;
			catLine.id = 'mw-normal-catlinks';&lt;br /&gt;
			catLine.style.textAlign = is_rtl ? 'right' : 'left';&lt;br /&gt;
			// Add a label&lt;br /&gt;
			var label = make( 'a' );&lt;br /&gt;
			label.href = conf.wgArticlePath.replace( '$1', 'Special:Categories' );&lt;br /&gt;
			label.title = HC.categories;&lt;br /&gt;
			label.appendChild( make( HC.categories, true ) );&lt;br /&gt;
			catLine.appendChild( label );&lt;br /&gt;
			catLine.appendChild( make( ':', true ) );&lt;br /&gt;
			// Insert the new category line&lt;br /&gt;
			var container = ( hiddenCats ? hiddenCats.parentNode : document.getElementById( 'catlinks' ) );&lt;br /&gt;
			if ( !container ) {&lt;br /&gt;
				container = make( 'div' );&lt;br /&gt;
				container.id = 'catlinks';&lt;br /&gt;
				footer.parentNode.insertBefore( container, footer.nextSibling );&lt;br /&gt;
			}&lt;br /&gt;
			container.className = 'catlinks noprint';&lt;br /&gt;
			container.style.display = '';&lt;br /&gt;
			if ( !hiddenCats ) container.appendChild( catLine ); else container.insertBefore( catLine, hiddenCats );&lt;br /&gt;
		} // end if catLine exists&lt;br /&gt;
		if ( is_rtl ) catLine.dir = 'rtl';&lt;br /&gt;
&lt;br /&gt;
		// Create editors for all existing categories&lt;br /&gt;
&lt;br /&gt;
		function createEditors( line, is_hidden ) {&lt;br /&gt;
			var i;&lt;br /&gt;
			var cats = line.getElementsByTagName( 'li' );&lt;br /&gt;
			if ( cats.length ) {&lt;br /&gt;
				newDOM = true;&lt;br /&gt;
				line = cats[ 0 ].parentNode;&lt;br /&gt;
			} else {&lt;br /&gt;
				cats = line.getElementsByTagName( 'span' );&lt;br /&gt;
			}&lt;br /&gt;
			// Copy cats, otherwise it'll also magically contain our added spans as it is a live collection!&lt;br /&gt;
			var copyCats = new Array( cats.length );&lt;br /&gt;
			for ( i = 0; i &amp;lt; cats.length; i++ ) copyCats[ i ] = cats[ i ];&lt;br /&gt;
			for ( i = 0; i &amp;lt; copyCats.length; i++ ) {&lt;br /&gt;
				var test = isOnPage( copyCats[ i ] );&lt;br /&gt;
				if ( test !== null &amp;amp;&amp;amp; test.match !== null ) {&lt;br /&gt;
				// eslint-disable-next-line no-new&lt;br /&gt;
					new CategoryEditor( line, copyCats[ i ], test.title, test.match[ 2 ], is_hidden );&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return copyCats.length ? copyCats[ copyCats.length - 1 ] : null;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		var lastSpan = createEditors( catLine, false );&lt;br /&gt;
		// Create one to add a new category&lt;br /&gt;
		// eslint-disable-next-line no-new&lt;br /&gt;
		new CategoryEditor( newDOM ? catLine.getElementsByTagName( 'ul' )[ 0 ] : catLine, null, null, lastSpan !== null, false );&lt;br /&gt;
		if ( !onUpload ) {&lt;br /&gt;
			if ( pageText !== null &amp;amp;&amp;amp; hiddenCats ) {&lt;br /&gt;
				if ( is_rtl ) hiddenCats.dir = 'rtl';&lt;br /&gt;
				createEditors( hiddenCats, true );&lt;br /&gt;
			}&lt;br /&gt;
			// And finally add the &amp;quot;multi-mode&amp;quot; span. (Do this at the end, otherwise it ends up in the list above.)&lt;br /&gt;
			var enableMulti = make( 'span' );&lt;br /&gt;
			enableMulti.className = 'noprint';&lt;br /&gt;
			if ( is_rtl ) enableMulti.dir = 'rtl';&lt;br /&gt;
			catLine.insertBefore( enableMulti, catLine.firstChild.nextSibling );&lt;br /&gt;
			enableMulti.appendChild( make( '\xa0', true ) ); // nbsp&lt;br /&gt;
			multiSpan = make( 'span' );&lt;br /&gt;
			enableMulti.appendChild( multiSpan );&lt;br /&gt;
			multiSpan.innerHTML = '(&amp;lt;a&amp;gt;' + HC.addmulti + '&amp;lt;/a&amp;gt;)';&lt;br /&gt;
			var lk = multiSpan.getElementsByTagName( 'a' )[ 0 ];&lt;br /&gt;
			lk.onclick = function ( evt ) {&lt;br /&gt;
				setMultiInput();&lt;br /&gt;
				checkMultiInput();&lt;br /&gt;
				return evtKill( evt );&lt;br /&gt;
			};&lt;br /&gt;
			lk.title = HC.multi_tooltip;&lt;br /&gt;
			lk.style.cursor = 'pointer';&lt;br /&gt;
		}&lt;br /&gt;
		cleanedText = null;&lt;br /&gt;
		if ( additionalWork instanceof Function ) additionalWork();&lt;br /&gt;
		setupCompleted.loaded(); // Trigger signal; execute registered functions&lt;br /&gt;
		$( 'body' ).trigger( 'hotcatSetupCompleted' );&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function createCommitForm() {&lt;br /&gt;
		if ( commitForm ) return;&lt;br /&gt;
		var formContainer = make( 'div' );&lt;br /&gt;
		formContainer.style.display = 'none';&lt;br /&gt;
		document.body.appendChild( formContainer );&lt;br /&gt;
		formContainer.innerHTML =&lt;br /&gt;
			'&amp;lt;form id=&amp;quot;hotcatCommitForm&amp;quot; method=&amp;quot;post&amp;quot; enctype=&amp;quot;multipart/form-data&amp;quot; action=&amp;quot;' +&lt;br /&gt;
			conf.wgScript + '?title=' + encodeURIComponent( conf.wgPageName ) + '&amp;amp;action=submit&amp;quot;&amp;gt;' +&lt;br /&gt;
			'&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;wpTextbox1&amp;quot;&amp;gt;' +&lt;br /&gt;
			'&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;model&amp;quot; value=&amp;quot;wikitext&amp;quot;&amp;gt;' +&lt;br /&gt;
			'&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;format&amp;quot; value=&amp;quot;text/x-wiki&amp;quot;&amp;gt;' +&lt;br /&gt;
			'&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;wpSummary&amp;quot; value=&amp;quot;&amp;quot;&amp;gt;' +&lt;br /&gt;
			'&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;wpMinoredit&amp;quot; value=&amp;quot;1&amp;quot;&amp;gt;' +&lt;br /&gt;
			'&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;wpWatchthis&amp;quot; value=&amp;quot;1&amp;quot;&amp;gt;' +&lt;br /&gt;
			'&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;wpAutoSummary&amp;quot; value=&amp;quot;d41d8cd98f00b204e9800998ecf8427e&amp;quot;&amp;gt;' +&lt;br /&gt;
			'&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;wpEdittime&amp;quot;&amp;gt;' +&lt;br /&gt;
			'&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;wpStarttime&amp;quot;&amp;gt;' +&lt;br /&gt;
			'&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;wpDiff&amp;quot; value=&amp;quot;wpDiff&amp;quot;&amp;gt;' +&lt;br /&gt;
			'&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;oldid&amp;quot; value=&amp;quot;0&amp;quot;&amp;gt;' +&lt;br /&gt;
			'&amp;lt;input type=&amp;quot;submit&amp;quot; name=&amp;quot;hcCommit&amp;quot; value=&amp;quot;hcCommit&amp;quot;&amp;gt;' +&lt;br /&gt;
			'&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;wpEditToken&amp;quot;&amp;gt;' +&lt;br /&gt;
			'&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;wpUltimateParam&amp;quot; value=&amp;quot;1&amp;quot;&amp;gt;' +&lt;br /&gt;
			'&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;wpChangeTags&amp;quot;&amp;gt;' +&lt;br /&gt;
			'&amp;lt;input type=&amp;quot;hidden&amp;quot; value=&amp;quot;ℳ𝒲♥𝓊𝓃𝒾𝒸ℴ𝒹ℯ&amp;quot; name=&amp;quot;wpUnicodeCheck&amp;quot;&amp;gt;' +&lt;br /&gt;
			'&amp;lt;/form&amp;gt;';&lt;br /&gt;
		commitForm = document.getElementById( 'hotcatCommitForm' );&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function getPage() {&lt;br /&gt;
		// We know we have an article here.&lt;br /&gt;
		if ( !conf.wgArticleId ) {&lt;br /&gt;
			// Doesn't exist yet. Disable on non-existing User pages -- might be a global user page.&lt;br /&gt;
			if ( conf.wgNamespaceNumber === 2 ) return;&lt;br /&gt;
			pageText = '';&lt;br /&gt;
			pageTime = null;&lt;br /&gt;
			setup( createCommitForm );&lt;br /&gt;
		} else {&lt;br /&gt;
			var url = conf.wgServer + conf.wgScriptPath + '/api.php?format=json&amp;amp;callback=HotCat.start&amp;amp;action=query&amp;amp;rawcontinue=&amp;amp;titles=' +&lt;br /&gt;
			encodeURIComponent( conf.wgPageName ) +&lt;br /&gt;
			'&amp;amp;prop=info%7Crevisions&amp;amp;rvprop=content%7Ctimestamp%7Cids&amp;amp;meta=siteinfo&amp;amp;rvlimit=1&amp;amp;rvstartid=' +&lt;br /&gt;
			conf.wgCurRevisionId;&lt;br /&gt;
			var s = make( 'script' );&lt;br /&gt;
			s.src = armorUri( url );&lt;br /&gt;
			s.type = 'text/javascript';&lt;br /&gt;
			HC.start = function ( json ) {&lt;br /&gt;
				setPage( json );&lt;br /&gt;
				setup( createCommitForm );&lt;br /&gt;
			};&lt;br /&gt;
			document.getElementsByTagName( 'head' )[ 0 ].appendChild( s );&lt;br /&gt;
			setupTimeout = window.setTimeout( function () {&lt;br /&gt;
				setup( createCommitForm );&lt;br /&gt;
			}, 4000 ); // 4 sec, just in case getting the wikitext takes longer.&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function setState( state ) {&lt;br /&gt;
		var cats = state.split( '\n' );&lt;br /&gt;
		if ( !cats.length ) return null;&lt;br /&gt;
&lt;br /&gt;
		if ( initialized &amp;amp;&amp;amp; editors.length === 1 &amp;amp;&amp;amp; editors[ 0 ].isAddCategory ) {&lt;br /&gt;
			// Insert new spans and create new editors for them.&lt;br /&gt;
			var newSpans = [];&lt;br /&gt;
			var before = editors.length === 1 ? editors[ 0 ].span : null;&lt;br /&gt;
			var i;&lt;br /&gt;
			for ( i = 0; i &amp;lt; cats.length; i++ ) {&lt;br /&gt;
				if ( !cats[ i ].length ) continue;&lt;br /&gt;
				var cat = cats[ i ].split( '|' );&lt;br /&gt;
				var key = cat.length &amp;gt; 1 ? cat[ 1 ] : null;&lt;br /&gt;
				cat = cat[ 0 ];&lt;br /&gt;
				var lk = make( 'a' );&lt;br /&gt;
				lk.href = wikiPagePath( HC.category_canonical + ':' + cat );&lt;br /&gt;
				lk.appendChild( make( cat, true ) );&lt;br /&gt;
				lk.title = cat;&lt;br /&gt;
				var span = make( 'span' );&lt;br /&gt;
				span.appendChild( lk );&lt;br /&gt;
				if ( !i ) catLine.insertBefore( make( ' ', true ), before );&lt;br /&gt;
&lt;br /&gt;
				catLine.insertBefore( span, before );&lt;br /&gt;
				if ( before &amp;amp;&amp;amp; i + 1 &amp;lt; cats.length ) parent.insertBefore( make( ' | ', true ), before );&lt;br /&gt;
&lt;br /&gt;
				newSpans.push( {&lt;br /&gt;
					element: span,&lt;br /&gt;
					title: cat,&lt;br /&gt;
					key: key&lt;br /&gt;
				} );&lt;br /&gt;
			}&lt;br /&gt;
			// And change the last one...&lt;br /&gt;
			if ( before ) before.parentNode.insertBefore( make( ' | ', true ), before );&lt;br /&gt;
&lt;br /&gt;
			for ( i = 0; i &amp;lt; newSpans.length; i++ ) {&lt;br /&gt;
			// eslint-disable-next-line no-new&lt;br /&gt;
				new CategoryEditor( catLine, newSpans[ i ].element, newSpans[ i ].title, newSpans[ i ].key );&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return null;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function getState() {&lt;br /&gt;
		var result = null;&lt;br /&gt;
		for ( var i = 0; i &amp;lt; editors.length; i++ ) {&lt;br /&gt;
			var text = editors[ i ].currentCategory;&lt;br /&gt;
			var key = editors[ i ].currentKey;&lt;br /&gt;
			if ( text &amp;amp;&amp;amp; text.length ) {&lt;br /&gt;
				if ( key !== null ) text += '|' + key;&lt;br /&gt;
				if ( result === null ) result = text; else result += '\n' + text;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return result;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function really_run() {&lt;br /&gt;
		initialize();&lt;br /&gt;
&lt;br /&gt;
		if ( !HC.upload_disabled &amp;amp;&amp;amp; conf.wgNamespaceNumber === -1 &amp;amp;&amp;amp; conf.wgCanonicalSpecialPageName === 'Upload' &amp;amp;&amp;amp; conf.wgUserName ) {&lt;br /&gt;
			setup_upload();&lt;br /&gt;
			setup( function () {&lt;br /&gt;
				// Check for state restoration once the setup is done otherwise, but before signalling setup completion&lt;br /&gt;
				if ( window.UploadForm &amp;amp;&amp;amp; UploadForm.previous_hotcat_state ) UploadForm.previous_hotcat_state = setState( UploadForm.previous_hotcat_state );&lt;br /&gt;
			} );&lt;br /&gt;
		} else {&lt;br /&gt;
			if ( !conf.wgIsArticle || conf.wgAction !== 'view' || param( 'diff' ) !== null || param( 'oldid' ) !== null || !can_edit() || HC.disable() ) return;&lt;br /&gt;
			getPage();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function run() {&lt;br /&gt;
		if ( HC.started ) return;&lt;br /&gt;
		HC.started = true;&lt;br /&gt;
		loadTrigger.register( really_run );&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Export legacy functions&lt;br /&gt;
	window.hotcat_get_state = function () {&lt;br /&gt;
		return getState();&lt;br /&gt;
	};&lt;br /&gt;
	window.hotcat_set_state = function ( state ) {&lt;br /&gt;
		return setState( state );&lt;br /&gt;
	};&lt;br /&gt;
	window.hotcat_close_form = function () {&lt;br /&gt;
		closeForm();&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	// Make sure we don't get conflicts with AjaxCategories (core development that should one day&lt;br /&gt;
	// replace HotCat).&lt;br /&gt;
	mw.config.set( 'disableAJAXCategories', true );&lt;br /&gt;
&lt;br /&gt;
	// Run as soon as possible. This varies depending on MediaWiki version;&lt;br /&gt;
	// window's 'load' event is always safe, but usually we can do better than that.&lt;br /&gt;
&lt;br /&gt;
	if ( conf.wgCanonicalSpecialPageName !== 'Upload' ) {&lt;br /&gt;
		// Reload HotCat after (VE) edits (bug T103285)&lt;br /&gt;
		mw.hook( 'postEdit' ).add( function () {&lt;br /&gt;
			// Reset HotCat in case this is a soft reload (VE edit)&lt;br /&gt;
			catLine = null;&lt;br /&gt;
			editors = [];&lt;br /&gt;
			initialized = false;&lt;br /&gt;
			HC.started = false;&lt;br /&gt;
			run();&lt;br /&gt;
		} );&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// We can safely trigger just after user configuration is loaded. Also start HotCat if the user module fails to load.&lt;br /&gt;
	// Avoid using Promise methods of mw.loader.using as those aren't supported in older&lt;br /&gt;
	// MediaWiki versions.&lt;br /&gt;
	$.when( mw.loader.using( 'user' ), $.ready ).then( run );&lt;br /&gt;
}( jQuery, mediaWiki ) );&lt;br /&gt;
// &amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=MediaWiki:Gadget-section-Kategori/en&amp;diff=114</id>
		<title>MediaWiki:Gadget-section-Kategori/en</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=MediaWiki:Gadget-section-Kategori/en&amp;diff=114"/>
		<updated>2018-07-26T06:15:58Z</updated>

		<summary type="html">&lt;p&gt;Administrator: ←Membuat halaman berisi 'Tools for categories'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Tools for categories&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=MediaWiki:Gadget-Cat-a-lot/en&amp;diff=113</id>
		<title>MediaWiki:Gadget-Cat-a-lot/en</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=MediaWiki:Gadget-Cat-a-lot/en&amp;diff=113"/>
		<updated>2018-07-26T06:14:30Z</updated>

		<summary type="html">&lt;p&gt;Administrator: ←Membuat halaman berisi 'Cat-a-lot: A tool that helps with moving multiple files between categories or adding categories to search results.'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Cat-a-lot: A tool that helps with moving multiple files between categories or adding categories to search results.&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=MediaWiki:Gadgets-definition&amp;diff=112</id>
		<title>MediaWiki:Gadgets-definition</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=MediaWiki:Gadgets-definition&amp;diff=112"/>
		<updated>2018-07-26T06:13:39Z</updated>

		<summary type="html">&lt;p&gt;Administrator: ←Membuat halaman berisi '== Kategori == * Cat-a-lot[ResourceLoader|dependencies=mediawiki.util|type=general]|Cat-a-lot.js|Cat-a-lot.css'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Kategori ==&lt;br /&gt;
* Cat-a-lot[ResourceLoader|dependencies=mediawiki.util|type=general]|Cat-a-lot.js|Cat-a-lot.css&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=MediaWiki:Gadget-Cat-a-lot.css&amp;diff=111</id>
		<title>MediaWiki:Gadget-Cat-a-lot.css</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=MediaWiki:Gadget-Cat-a-lot.css&amp;diff=111"/>
		<updated>2018-07-26T06:11:47Z</updated>

		<summary type="html">&lt;p&gt;Administrator: ←Membuat halaman berisi '#cat_a_lot { 	bottom: 0; 	display: block; 	position: fixed; 	right: 0; 	z-index: 100; 	padding: 5px; 	box-shadow: 0 2px 4px rgba(0,0,0,0.5);  	background-color: #FEF6E...'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#cat_a_lot {&lt;br /&gt;
	bottom: 0;&lt;br /&gt;
	display: block;&lt;br /&gt;
	position: fixed;&lt;br /&gt;
	right: 0;&lt;br /&gt;
	z-index: 100;&lt;br /&gt;
	padding: 5px;&lt;br /&gt;
	box-shadow: 0 2px 4px rgba(0,0,0,0.5); &lt;br /&gt;
	background-color: #FEF6E7;&lt;br /&gt;
}&lt;br /&gt;
#cat_a_lot_data, #cat_a_lot_mark_counter {&lt;br /&gt;
	display: none;&lt;br /&gt;
}&lt;br /&gt;
#cat_a_lot_data ul {&lt;br /&gt;
	list-style-image: none;&lt;br /&gt;
	list-style-type: none;&lt;br /&gt;
	margin: 0 0 0 5px;&lt;br /&gt;
}&lt;br /&gt;
#cat_a_lot_selections, #cat_a_lot_mark_counter, #cat_a_lot_settings {&lt;br /&gt;
	background: url(/w/skins/Vector/images/portal-break.png) no-repeat;&lt;br /&gt;
	padding: 5px;&lt;br /&gt;
}&lt;br /&gt;
#cat_a_lot_remove {&lt;br /&gt;
	font-weight: bold;&lt;br /&gt;
	display: block;&lt;br /&gt;
}&lt;br /&gt;
a {&lt;br /&gt;
	cursor:pointer;&lt;br /&gt;
}&lt;br /&gt;
.cat_a_lot_move, .cat_a_lot_action {&lt;br /&gt;
	font-weight: bold;&lt;br /&gt;
}&lt;br /&gt;
.cat_a_lot_feedback {&lt;br /&gt;
	border: 1px #A9DE16 solid !important;&lt;br /&gt;
	background: #EAF2CB /*url(//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif)*/ no-repeat 8px 14px !important;&lt;br /&gt;
	padding-left: 2.85em !important;&lt;br /&gt;
	padding-top: 10px !important;&lt;br /&gt;
	font-size: 1.1em !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.cat_a_lot_done {&lt;br /&gt;
	background-image: url(//upload.wikimedia.org/wikipedia/commons/thumb/0/0e/Dialog-apply.svg/50px-Dialog-apply.svg.png) !important;&lt;br /&gt;
	background-position: 8px 50% !important;&lt;br /&gt;
	padding-top: 0 !important;&lt;br /&gt;
}&lt;br /&gt;
#cat_a_lot_searchcatname {&lt;br /&gt;
	font-size: 112%;&lt;br /&gt;
	margin: -5px 0 5px -5px;&lt;br /&gt;
	width: 100%;&lt;br /&gt;
}&lt;br /&gt;
.skin-vector #cat_a_lot {&lt;br /&gt;
	font-size: .75em;&lt;br /&gt;
}&lt;br /&gt;
.cat_a_lot_markAsDone {&lt;br /&gt;
	background-color: #BBB !important;&lt;br /&gt;
}&lt;br /&gt;
.cat_a_lot_selected {&lt;br /&gt;
	background-color: #DF6 !important;&lt;br /&gt;
}&lt;br /&gt;
#cat_a_lot_no_found, #cat_a_lot_last_selected, #cat_a_lot_settings {&lt;br /&gt;
	font-weight:bold;&lt;br /&gt;
}&lt;br /&gt;
#cat_a_lot_last_selected {&lt;br /&gt;
	outline:1px dotted #999;&lt;br /&gt;
}&lt;br /&gt;
#cat_a_lot_category_list table {&lt;br /&gt;
	border-collapse: collapse;&lt;br /&gt;
}&lt;br /&gt;
#cat_a_lot_category_list tr:hover {&lt;br /&gt;
	background-color: #fc3;&lt;br /&gt;
}&lt;br /&gt;
#cat_a_lot_category_list {&lt;br /&gt;
	overflow: auto;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=MediaWiki:Gadget-Cat-a-lot.js&amp;diff=110</id>
		<title>MediaWiki:Gadget-Cat-a-lot.js</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=MediaWiki:Gadget-Cat-a-lot.js&amp;diff=110"/>
		<updated>2018-07-26T06:11:05Z</updated>

		<summary type="html">&lt;p&gt;Administrator: ←Membuat halaman berisi '/** * Cat-a-lot * Changes category of multiple files * * @rev 00:13, 10 February 2018 (UTC) * @author Originally by Magnus Manske (2007) * @author RegExes by Ilmari Ka...'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/**&lt;br /&gt;
* Cat-a-lot&lt;br /&gt;
* Changes category of multiple files&lt;br /&gt;
*&lt;br /&gt;
* @rev 00:13, 10 February 2018 (UTC)&lt;br /&gt;
* @author Originally by Magnus Manske (2007)&lt;br /&gt;
* @author RegExes by Ilmari Karonen (2010)&lt;br /&gt;
* @author Completely rewritten by DieBuche (2010-2012)&lt;br /&gt;
* @author Rillke (2012-2014)&lt;br /&gt;
* @author Perhelion (2017)&lt;br /&gt;
&lt;br /&gt;
* Requires [[MediaWiki:Gadget-SettingsManager.js]] and [[MediaWiki:Gadget-SettingsUI.js]] (properly registered) for per-user-settings&lt;br /&gt;
*&lt;br /&gt;
* READ THIS PAGE IF YOU WANT TO TRANSLATE OR USE THIS ON ANOTHER SITE:&lt;br /&gt;
* http://commons.wikimedia.org/wiki/MediaWiki:Gadget-Cat-a-lot.js/translating&lt;br /&gt;
* &amp;lt;nowiki&amp;gt;&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/* global jQuery, mediaWiki */&lt;br /&gt;
/* eslint one-var:0, vars-on-top:0, no-underscore-dangle:0, valid-jsdoc:0,&lt;br /&gt;
curly:0, camelcase:0, no-useless-escape:0, no-alert:0 */ // extends: wikimedia&lt;br /&gt;
/* jshint unused:true, forin:false, smarttabs:true, loopfunc:true, browser:true */&lt;br /&gt;
&lt;br /&gt;
( function ( $, mw ) {&lt;br /&gt;
'use strict';&lt;br /&gt;
&lt;br /&gt;
var formattedNS = mw.config.get( 'wgFormattedNamespaces' ),&lt;br /&gt;
	ns = mw.config.get( 'wgNamespaceNumber' ),&lt;br /&gt;
	nsIDs = mw.config.get( 'wgNamespaceIds' ),&lt;br /&gt;
	userGrp = mw.config.get( 'wgUserGroups' ),&lt;br /&gt;
	project = mw.config.get( 'wgDBname' );&lt;br /&gt;
&lt;br /&gt;
var msgs = {&lt;br /&gt;
// Preferences&lt;br /&gt;
// new: added 2012-09-19. Please translate.&lt;br /&gt;
// Use user language for i18n&lt;br /&gt;
	'cat-a-lot-watchlistpref': 'Watchlist preference concerning files edited with Cat-a-lot',&lt;br /&gt;
	'cat-a-lot-watch_pref': 'According to your general preferences',&lt;br /&gt;
	'cat-a-lot-watch_nochange': 'Do not change watchstatus',&lt;br /&gt;
	'cat-a-lot-watch_watch': 'Watch pages edited with Cat-a-lot',&lt;br /&gt;
	'cat-a-lot-watch_unwatch': 'Remove pages while editing with Cat-a-lot from your watchlist',&lt;br /&gt;
	'cat-a-lot-minorpref': 'Mark edits as minor (if you generally mark your edits as minor, this won’t change anything)',&lt;br /&gt;
	'cat-a-lot-editpagespref': 'Allow categorising pages (including categories) that are not files',&lt;br /&gt;
	'cat-a-lot-docleanuppref': 'Remove {{Check categories}} and other minor cleanup',&lt;br /&gt;
	'cat-a-lot-uncatpref': 'Remove {{Uncategorized}}',&lt;br /&gt;
	'cat-a-lot-subcatcountpref': 'Sub-categories to show at most',&lt;br /&gt;
	'cat-a-lot-config-settings': 'Preferences',&lt;br /&gt;
	'cat-a-lot-buttonpref': 'Use buttons instead of text-links',&lt;br /&gt;
	'cat-a-lot-comment-label': 'Custom edit comment',&lt;br /&gt;
	'cat-a-lot-edit-question': 'Why is this change necessary?',&lt;br /&gt;
&lt;br /&gt;
	// Progress&lt;br /&gt;
	// 'cat-a-lot-loading': 'Loading …',&lt;br /&gt;
	'cat-a-lot-editing': 'Editing page',&lt;br /&gt;
	'cat-a-lot-of': 'of ',&lt;br /&gt;
	'cat-a-lot-skipped-already': 'The following {{PLURAL:$1|1=page was|$1 pages were}} skipped, because the page was already in the category:',&lt;br /&gt;
	'cat-a-lot-skipped-not-found': 'The following {{PLURAL:$1|1=page was|$1 pages were}} skipped, because the old category could not be found:',&lt;br /&gt;
	'cat-a-lot-skipped-server': 'The following {{PLURAL:$1|1=page|$1 pages}} couldn’t be changed, since there were problems connecting to the server:',&lt;br /&gt;
	'cat-a-lot-all-done': 'All pages are processed.',&lt;br /&gt;
	'cat-a-lot-done': 'Done!', // mw.msg(&amp;quot;Feedback-close&amp;quot;)&lt;br /&gt;
	'cat-a-lot-added-cat': 'Added category $1',&lt;br /&gt;
	'cat-a-lot-copied-cat': 'Copied to category $1',&lt;br /&gt;
	'cat-a-lot-moved-cat': 'Moved to category $1',&lt;br /&gt;
	'cat-a-lot-removed-cat': 'Removed from category $1',&lt;br /&gt;
	// 'cat-a-lot-return-to-page': 'Return to page',&lt;br /&gt;
	// 'cat-a-lot-cat-not-found': 'Category not found.',&lt;br /&gt;
&lt;br /&gt;
	// as in 17 files selected&lt;br /&gt;
	'cat-a-lot-files-selected': '{{PLURAL:$1|1=One file|$1 files}} selected.',&lt;br /&gt;
	'cat-a-lot-pe_file': '$1 {{PLURAL:$1|page|pages}} of $2 affected',&lt;br /&gt;
	'cat-a-lot-parent-cat': 'Has parent-category: ',&lt;br /&gt;
	'cat-a-lot-sub-cat': 'Has sub-category: ',&lt;br /&gt;
&lt;br /&gt;
	// Actions&lt;br /&gt;
	'cat-a-lot-copy': 'Copy',&lt;br /&gt;
	'cat-a-lot-move': 'Move',&lt;br /&gt;
	'cat-a-lot-add': 'Add',&lt;br /&gt;
	// 'cat-a-lot-remove-from-cat': 'Remove from this category',&lt;br /&gt;
	'cat-a-lot-overcat': 'Check over-categorization',&lt;br /&gt;
	'cat-a-lot-enter-name': 'Enter category name',&lt;br /&gt;
	'cat-a-lot-select': 'Select',&lt;br /&gt;
	'cat-a-lot-all': 'all',&lt;br /&gt;
	'cat-a-lot-none': 'none',&lt;br /&gt;
	// 'cat-a-lot-none-selected': 'No files selected!', 'Ooui-selectfile-placeholder'&lt;br /&gt;
&lt;br /&gt;
	// Summaries (project language):&lt;br /&gt;
	'cat-a-lot-pref-save-summary': 'Updating user preferences',&lt;br /&gt;
	'cat-a-lot-summary-add': 'Adding [[Category:$1]]',&lt;br /&gt;
	'cat-a-lot-summary-copy': 'Copying from [[Category:$1]] to [[Category:$2]]',&lt;br /&gt;
	'cat-a-lot-summary-move': 'Moving from [[Category:$1]] to [[Category:$2]]',&lt;br /&gt;
	'cat-a-lot-summary-remove': 'Removing from [[Category:$1]]',&lt;br /&gt;
	'cat-a-lot-prefix-summary': '',&lt;br /&gt;
	'cat-a-lot-using-summary': ' using [[c:Help:Cat-a-lot|Cat-a-lot]]'&lt;br /&gt;
};&lt;br /&gt;
mw.messages.set( msgs );&lt;br /&gt;
&lt;br /&gt;
function msg( /* params */ ) {&lt;br /&gt;
	var args = Array.prototype.slice.call( arguments, 0 );&lt;br /&gt;
	args[ 0 ] = 'cat-a-lot-' + args[ 0 ];&lt;br /&gt;
	return ( args.length === 1 ) ?&lt;br /&gt;
		mw.message( args[ 0 ] ).plain() :&lt;br /&gt;
		mw.message.apply( mw.message, args ).parse();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// There is only one Cat-a-lot on one page&lt;br /&gt;
var $body, $container, $dataContainer, $searchInputContainer, $searchInput, $resultList, $markCounter, $selections,&lt;br /&gt;
	$selectFiles, $selectPages, $selectNone, $selectInvert, $settingsWrapper, $settingsLink, $head, $link, $overcat,&lt;br /&gt;
	commonsURL = 'https://commons.wikimedia.org/w/index.php',&lt;br /&gt;
	is_rtl = $( 'body' ).hasClass( 'rtl' ),&lt;br /&gt;
	reCat, // localized category search regexp&lt;br /&gt;
	non,&lt;br /&gt;
	r; // result file count for overcat&lt;br /&gt;
&lt;br /&gt;
var CAL = mw.libs.catALot = {&lt;br /&gt;
	apiUrl: mw.util.wikiScript( 'api' ),&lt;br /&gt;
	origin: '',&lt;br /&gt;
	searchmode: false,&lt;br /&gt;
	version: '4.77',&lt;br /&gt;
	setHeight: 450,&lt;br /&gt;
	changeTag: 'Cat-a-lot',&lt;br /&gt;
&lt;br /&gt;
	settings: {&lt;br /&gt;
	/* Any category in this category is deemed a disambiguation category; i.e., a category that should not contain&lt;br /&gt;
any items, but that contains links to other categories where stuff should be categorized. If you don't have&lt;br /&gt;
that concept on your wiki, set it to null. Use blanks, not underscores. */&lt;br /&gt;
		disambig_category: 'Disambiguation', // Commons and EnWP&lt;br /&gt;
		/* Any category in this category is deemed a (soft) redirect to some other category defined by a link&lt;br /&gt;
* to another non-blacklisted category. If your wiki doesn't have soft category redirects, set this to null.&lt;br /&gt;
* If a soft-redirected category contains more than one link to another non-blacklisted category, it's considered&lt;br /&gt;
* a disambiguation category instead. */&lt;br /&gt;
		redir_category: 'Category redirects'&lt;br /&gt;
&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	init: function () {&lt;br /&gt;
		// Prevent historical double marker (maybe remove in future)&lt;br /&gt;
		if ( /Cat-?a-?lot/i.test( msgs[ 'cat-a-lot-pref-save-summary' ] ) ) { mw.messages.set( { 'cat-a-lot-prefix-summary': '', 'cat-a-lot-using-summary': '' } ); } else {&lt;br /&gt;
			mw.messages.set( {&lt;br /&gt;
				'cat-a-lot-pref-save-summary': msgs[ 'cat-a-lot-prefix-summary' ] + msgs[ 'cat-a-lot-pref-save-summary' ] + msgs[ 'cat-a-lot-using-summary' ]&lt;br /&gt;
			} );&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// TODO: better extern project support for possible change-tag? (needs currently change after init)&lt;br /&gt;
		if ( project === 'commonswiki' ) { mw.messages.set( { 'cat-a-lot-using-summary': '' } ); } else { // Reset&lt;br /&gt;
			this.changeTag = '';&lt;br /&gt;
			this.settings.redir_category = '';&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		this._initSettings();&lt;br /&gt;
		$body = $( document.body );&lt;br /&gt;
		$container = $( '&amp;lt;div&amp;gt;' )&lt;br /&gt;
			.attr( 'id', 'cat_a_lot' )&lt;br /&gt;
			.appendTo( $body );&lt;br /&gt;
		$dataContainer = $( '&amp;lt;div&amp;gt;' )&lt;br /&gt;
			.attr( 'id', 'cat_a_lot_data' )&lt;br /&gt;
			.appendTo( $container );&lt;br /&gt;
		$searchInputContainer = $( '&amp;lt;div&amp;gt;' )&lt;br /&gt;
			.appendTo( $dataContainer );&lt;br /&gt;
		$searchInput = $( '&amp;lt;input&amp;gt;', {&lt;br /&gt;
			id: 'cat_a_lot_searchcatname',&lt;br /&gt;
			placeholder: msg( 'enter-name' ),&lt;br /&gt;
			type: 'text'&lt;br /&gt;
		} )&lt;br /&gt;
			.appendTo( $searchInputContainer );&lt;br /&gt;
		$resultList = $( '&amp;lt;div&amp;gt;' )&lt;br /&gt;
			.attr( 'id', 'cat_a_lot_category_list' )&lt;br /&gt;
			.appendTo( $dataContainer );&lt;br /&gt;
		$markCounter = $( '&amp;lt;div&amp;gt;' )&lt;br /&gt;
			.attr( 'id', 'cat_a_lot_mark_counter' )&lt;br /&gt;
			.appendTo( $dataContainer );&lt;br /&gt;
		$selections = $( '&amp;lt;div&amp;gt;' )&lt;br /&gt;
			.attr( 'id', 'cat_a_lot_selections' )&lt;br /&gt;
			.text( msg( 'select' ) + ':' )&lt;br /&gt;
			.appendTo( $dataContainer );&lt;br /&gt;
		$settingsWrapper = $( '&amp;lt;div&amp;gt;' )&lt;br /&gt;
			.attr( 'id', 'cat_a_lot_settings' )&lt;br /&gt;
			.appendTo( $dataContainer );&lt;br /&gt;
		$settingsLink = $( '&amp;lt;a&amp;gt;', {&lt;br /&gt;
			id: 'cat_a_lot_config_settings',&lt;br /&gt;
			title: 'Version ' + this.version,&lt;br /&gt;
			text: msg( 'config-settings' )&lt;br /&gt;
		} )&lt;br /&gt;
			.appendTo( $settingsWrapper );&lt;br /&gt;
		$head = $( '&amp;lt;div&amp;gt;' )&lt;br /&gt;
			.attr( 'id', 'cat_a_lot_head' )&lt;br /&gt;
			.appendTo( $container );&lt;br /&gt;
		$link = $( '&amp;lt;a&amp;gt;' )&lt;br /&gt;
			.attr( 'id', 'cat_a_lot_toggle' )&lt;br /&gt;
			.text( 'Cat-a-lot' )&lt;br /&gt;
			.appendTo( $head );&lt;br /&gt;
		$settingsWrapper.append( $( '&amp;lt;a&amp;gt;', {&lt;br /&gt;
			href: commonsURL + '?title=Special:MyLanguage/Help:Gadget-Cat-a-lot',&lt;br /&gt;
			target: '_blank',&lt;br /&gt;
			style: 'float:right',&lt;br /&gt;
			title: ( $( '#n-help a' ).attr( 'title' ) || '' ) + ' (v. ' + this.version + ')'&lt;br /&gt;
		} ).text( '?' ) );&lt;br /&gt;
		$container.one( 'mouseover', function () { // Try load on demand earliest as possible&lt;br /&gt;
			mw.loader.load( [ 'jquery.ui.resizable', 'jquery.ui.draggable' ] );&lt;br /&gt;
		} );&lt;br /&gt;
&lt;br /&gt;
		if ( this.origin &amp;amp;&amp;amp; !non ) {&lt;br /&gt;
			$overcat = $( '&amp;lt;a&amp;gt;' )&lt;br /&gt;
				.attr( 'id', 'cat_a_lot_overcat' )&lt;br /&gt;
				.html( msg( 'overcat' ) )&lt;br /&gt;
				.on( 'click', function ( e ) {&lt;br /&gt;
					CAL.getOverCat( e );&lt;br /&gt;
				} )&lt;br /&gt;
				.insertBefore( $selections );&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if ( ( mw.util.getParamValue( 'withJS' ) === 'MediaWiki:Gadget-Cat-a-lot.js' &amp;amp;&amp;amp;&lt;br /&gt;
			!mw.util.getParamValue( 'withCSS' ) ) ||&lt;br /&gt;
			mw.loader.getState( 'ext.gadget.Cat-a-lot' ) === 'registered' ) {&lt;br /&gt;
			mw.loader.load( mw.config.get( 'wgServer' ) + '/w/index.php?title=MediaWiki:Gadget-Cat-a-lot.css&amp;amp;action=raw&amp;amp;ctype=text/css', 'text/css' );&lt;br /&gt;
			// importStylesheet( 'MediaWiki:Gadget-Cat-a-lot.css' );&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		reCat = new RegExp( '^\\s*' + CAL.localizedRegex( 14, 'Category' ) + ':', '' );&lt;br /&gt;
&lt;br /&gt;
		$searchInput.on( 'keypress', function ( e ) {&lt;br /&gt;
			if ( e.which === 13 ) {&lt;br /&gt;
				CAL.updateCats( $.trim( $( this ).val().replace( /[\u200E\u200F\u202A-\u202E]/g, '' ) ) );&lt;br /&gt;
				mw.cookie.set( 'catAlot', CAL.currentCategory );&lt;br /&gt;
			}&lt;br /&gt;
		} )&lt;br /&gt;
			.on( 'input keyup', function () {&lt;br /&gt;
				var oldVal = this.value,&lt;br /&gt;
					newVal = oldVal.replace( reCat, '' );&lt;br /&gt;
				if ( newVal !== oldVal ) { this.value = newVal; }&lt;br /&gt;
&lt;br /&gt;
				if ( !newVal ) { mw.cookie.set( 'catAlot', null ); }&lt;br /&gt;
			} );&lt;br /&gt;
&lt;br /&gt;
		function initAutocomplete() {&lt;br /&gt;
			if ( CAL.autoCompleteIsEnabled ) { return; }&lt;br /&gt;
&lt;br /&gt;
			CAL.autoCompleteIsEnabled = true;&lt;br /&gt;
&lt;br /&gt;
			if ( !$searchInput.val() &amp;amp;&amp;amp; mw.cookie &amp;amp;&amp;amp; mw.cookie.get( 'catAlot' ) ) { $searchInput.val( mw.cookie.get( 'catAlot' ) ); }&lt;br /&gt;
&lt;br /&gt;
			$searchInput.autocomplete( {&lt;br /&gt;
				source: function ( request, response ) {&lt;br /&gt;
					CAL.doAPICall( {&lt;br /&gt;
						action: 'opensearch',&lt;br /&gt;
						search: request.term,&lt;br /&gt;
						redirects: 'resolve',&lt;br /&gt;
						namespace: 14&lt;br /&gt;
					}, function ( data ) {&lt;br /&gt;
						if ( data[ 1 ] ) {&lt;br /&gt;
							response( $( data[ 1 ] )&lt;br /&gt;
								.map( function ( index, item ) {&lt;br /&gt;
									return item.replace( reCat, '' );&lt;br /&gt;
								} ) );&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
					} );&lt;br /&gt;
				},&lt;br /&gt;
				open: function () {&lt;br /&gt;
					$( '.ui-autocomplete' )&lt;br /&gt;
						.position( {&lt;br /&gt;
							my: is_rtl ? 'left bottom' : 'right bottom',&lt;br /&gt;
							at: is_rtl ? 'left top' : 'right top',&lt;br /&gt;
							of: $searchInput&lt;br /&gt;
						} );&lt;br /&gt;
				},&lt;br /&gt;
				appendTo: '#cat_a_lot'&lt;br /&gt;
			} );&lt;br /&gt;
		}&lt;br /&gt;
		$( '&amp;lt;a&amp;gt;' )&lt;br /&gt;
		// .attr( 'id', 'cat_a_lot_select_all' )&lt;br /&gt;
			.text( msg( 'all' ) )&lt;br /&gt;
			.on( 'click', function () {&lt;br /&gt;
				CAL.toggleAll( true );&lt;br /&gt;
			} )&lt;br /&gt;
			.appendTo( $selections.append( ' ' ) );&lt;br /&gt;
		if ( this.settings.editpages ) {&lt;br /&gt;
			$selectFiles = $( '&amp;lt;a&amp;gt;' )&lt;br /&gt;
				.on( 'click', function () {&lt;br /&gt;
					CAL.toggleAll( 'files' );&lt;br /&gt;
				} );&lt;br /&gt;
			$selectPages = $( '&amp;lt;a&amp;gt;' )&lt;br /&gt;
				.on( 'click', function () {&lt;br /&gt;
					CAL.toggleAll( 'pages' );&lt;br /&gt;
				} );&lt;br /&gt;
			$selections.append( $( '&amp;lt;span&amp;gt;' ).hide().append( [ ' / ', $selectFiles, ' / ', $selectPages ] ) );&lt;br /&gt;
		}&lt;br /&gt;
		$selectNone = $( '&amp;lt;a&amp;gt;' )&lt;br /&gt;
		// .attr( 'id', 'cat_a_lot_select_none' )&lt;br /&gt;
			.text( msg( 'none' ) )&lt;br /&gt;
			.on( 'click', function () {&lt;br /&gt;
				CAL.toggleAll( false );&lt;br /&gt;
			} );&lt;br /&gt;
		$selectInvert = $( '&amp;lt;a&amp;gt;' )&lt;br /&gt;
			.on( 'click', function () {&lt;br /&gt;
				CAL.toggleAll( null );&lt;br /&gt;
			} );&lt;br /&gt;
		$selections.append( [ ' • ', $selectNone, ' • ', $selectInvert,&lt;br /&gt;
			$( '&amp;lt;div&amp;gt;' ).append( [&lt;br /&gt;
				$( '&amp;lt;label&amp;gt;' )&lt;br /&gt;
					.attr( {&lt;br /&gt;
						'for': 'cat_a_lot_comment',&lt;br /&gt;
						style: 'line-height:1.5em;vertical-align:bottom'&lt;br /&gt;
					} )&lt;br /&gt;
					.text( msg( 'comment-label' ) ),&lt;br /&gt;
				$( '&amp;lt;input&amp;gt;' )&lt;br /&gt;
					.attr( {&lt;br /&gt;
						id: 'cat_a_lot_comment',&lt;br /&gt;
						type: 'checkbox'&lt;br /&gt;
					} )&lt;br /&gt;
			] )&lt;br /&gt;
		] );&lt;br /&gt;
&lt;br /&gt;
		$link&lt;br /&gt;
			.on( 'click', function () {&lt;br /&gt;
				$( this ).toggleClass( 'cat_a_lot_enabled' );&lt;br /&gt;
				// Load autocomplete on demand&lt;br /&gt;
				mw.loader.using( 'jquery.ui.autocomplete', initAutocomplete );&lt;br /&gt;
&lt;br /&gt;
				if ( !CAL.executed ) {&lt;br /&gt;
					$.when( mw.loader.using( [&lt;br /&gt;
						'jquery.ui.resizable',&lt;br /&gt;
						'jquery.ui.draggable',&lt;br /&gt;
						'jquery.ui.button',&lt;br /&gt;
						'mediawiki.api.messages',&lt;br /&gt;
						'mediawiki.jqueryMsg'&lt;br /&gt;
					] ), $.ready )&lt;br /&gt;
						.then( function () {&lt;br /&gt;
							return new mw.Api().loadMessagesIfMissing( [&lt;br /&gt;
								'Cancel',&lt;br /&gt;
								'Categorytree-not-found',&lt;br /&gt;
								// 'Checkuser-all',&lt;br /&gt;
								// 'Code-field-select',&lt;br /&gt;
								// 'Export-addcat',&lt;br /&gt;
								'Filerevert-submit',&lt;br /&gt;
								'Mobile-frontend-return-to-page',&lt;br /&gt;
								'Ooui-selectfile-placeholder',&lt;br /&gt;
								// 'Visualeditor-clipboard-copy',&lt;br /&gt;
								'Wikieditor-loading',&lt;br /&gt;
								'Prefs-files',&lt;br /&gt;
								'Categories',&lt;br /&gt;
								'Checkbox-invert',&lt;br /&gt;
								'Centralnotice-remove', // 'Ooui-item-remove'&lt;br /&gt;
								'Apifeatureusage-warnings'&lt;br /&gt;
							] );&lt;br /&gt;
						} ).then( function () {&lt;br /&gt;
							CAL.run();&lt;br /&gt;
						} );&lt;br /&gt;
				} else { CAL.run(); }&lt;br /&gt;
			} );&lt;br /&gt;
		$settingsLink&lt;br /&gt;
			.on( 'click', CAL.manageSettings );&lt;br /&gt;
		this.localCatName = formattedNS[ 14 ] + ':';&lt;br /&gt;
		mw.loader.using( 'mediawiki.cookie', function () { // Let catAlot stay open&lt;br /&gt;
			var val = mw.cookie.get( 'catAlotO' );&lt;br /&gt;
			if ( val &amp;amp;&amp;amp; Number( val ) === ns ) { $link.click(); }&lt;br /&gt;
		}&lt;br /&gt;
		);&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	getOverCat: function ( e ) {&lt;br /&gt;
		var files = [];&lt;br /&gt;
		r = 0; // result counter&lt;br /&gt;
		if ( e ) {&lt;br /&gt;
			e.preventDefault();&lt;br /&gt;
			this.files = this.getMarkedLabels(); // .toArray() not working&lt;br /&gt;
			for ( var f = 0; f &amp;lt; this.files.length; f++ ) { files.push( this.files[ f ] ); }&lt;br /&gt;
&lt;br /&gt;
		}&lt;br /&gt;
		if ( !files.length || !( files instanceof Array ) ) { return alert( mw.msg( 'Ooui-selectfile-placeholder' ) ); }&lt;br /&gt;
		this.files = files;&lt;br /&gt;
		mw.loader.using( [ 'jquery.spinner' ], function () {&lt;br /&gt;
			$markCounter.injectSpinner( 'overcat' );&lt;br /&gt;
			CAL.getFileCats();&lt;br /&gt;
		} );&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	getFileCats: function () {&lt;br /&gt;
		var aLen = this.files.length;&lt;br /&gt;
		var bLen = this.selectedLabels.length;&lt;br /&gt;
		var file = this.files[ aLen - 1 ][ 0 ];&lt;br /&gt;
		$overcat.text( '…' + aLen + '\/' + bLen );&lt;br /&gt;
		if ( file ) {&lt;br /&gt;
			this.doAPICall( {&lt;br /&gt;
				prop: 'categories',&lt;br /&gt;
				titles: file&lt;br /&gt;
			}, this.checkFileCats&lt;br /&gt;
			);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	checkFileCats: function ( data ) {&lt;br /&gt;
		var cc = 0; // current cat counter;&lt;br /&gt;
		var file = CAL.files.pop();&lt;br /&gt;
		if ( data.query &amp;amp;&amp;amp; data.query.pages ) {&lt;br /&gt;
			$.each( data.query.pages, function ( id, page ) {&lt;br /&gt;
				if ( page.categories ) {&lt;br /&gt;
					var target = file[ 1 ].removeClass( 'cat_a_lot_selected' );&lt;br /&gt;
					$.each( page.categories, function ( c, cat ) {&lt;br /&gt;
						var title = cat.title.replace( reCat, '' ),&lt;br /&gt;
							color = 'orange',&lt;br /&gt;
							mark = function ( kind ) { // kind of category&lt;br /&gt;
							// TODO: store data to use this for special remove function&lt;br /&gt;
								if ( kind === 'sub' ) { color = 'green'; }&lt;br /&gt;
								var border = '3px dotted ';&lt;br /&gt;
								if ( $.inArray( title, CAL[ kind + 'Cats' ] ) !== -1 ) {&lt;br /&gt;
									cc++;&lt;br /&gt;
									target = target.parents( '.gallerybox' );&lt;br /&gt;
									target = target[ 0 ] ? target : file[ 1 ];&lt;br /&gt;
									target.css( {&lt;br /&gt;
										border: border + color&lt;br /&gt;
									} ).prop( 'title', msg( kind + '-cat' ) + title );&lt;br /&gt;
									color = 'red';&lt;br /&gt;
									return false;&lt;br /&gt;
								}&lt;br /&gt;
							};&lt;br /&gt;
						mark( 'sub' );&lt;br /&gt;
						return mark( 'parent' );&lt;br /&gt;
					} );&lt;br /&gt;
					if ( cc ) { r++; }&lt;br /&gt;
				}&lt;br /&gt;
			} );&lt;br /&gt;
		} else { mw.log( 'Api-fail', file, data ); }&lt;br /&gt;
		if ( CAL.files[ 0 ] ) { return setTimeout( function () { CAL.getFileCats(); }, 100 ); } // Api has bad performance here, so we can get only each file separately&lt;br /&gt;
		$overcat.text( msg( 'pe_file', r, CAL.selectedLabels.length ) );&lt;br /&gt;
		$.removeSpinner( 'overcat' );&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	findAllLabels: function ( searchmode ) {&lt;br /&gt;
	// It's possible to allow any kind of pages as well but what happens if you click on &amp;quot;select all&amp;quot; and don't expect it&lt;br /&gt;
		switch ( searchmode ) {&lt;br /&gt;
			case 'search':&lt;br /&gt;
				this.labels = this.labels.add( $( 'table.searchResultImage' ).find( 'tr&amp;gt;td:eq(1)' ) );&lt;br /&gt;
				if ( this.settings.editpages ) { this.labels = this.labels.add( 'div.mw-search-result-heading' ); }&lt;br /&gt;
&lt;br /&gt;
				break;&lt;br /&gt;
			case 'category':&lt;br /&gt;
				this.findAllLabels( 'gallery' );&lt;br /&gt;
				this.labels = this.labels.add( $( '#mw-category-media' ).find( 'li[class!=&amp;quot;gallerybox&amp;quot;]' ) );&lt;br /&gt;
				if ( this.settings.editpages ) {&lt;br /&gt;
					this.pageLabels = $( '#mw-pages, #mw-subcategories' ).find( 'li' );&lt;br /&gt;
					// this.files = this.labels;&lt;br /&gt;
					this.labels = this.labels.add( this.pageLabels );&lt;br /&gt;
				}&lt;br /&gt;
				break;&lt;br /&gt;
			case 'contribs':&lt;br /&gt;
				this.labels = this.labels.add( $( 'ul.mw-contributions-list li' ) );&lt;br /&gt;
				// FIXME: Filter if !this.settings.editpages&lt;br /&gt;
				break;&lt;br /&gt;
			case 'prefix':&lt;br /&gt;
				this.labels = this.labels.add( $( 'ul.mw-prefixindex-list li' ) );&lt;br /&gt;
				break;&lt;br /&gt;
			case 'listfiles':&lt;br /&gt;
			// this.labels = this.labels.add( $( 'table.listfiles&amp;gt;tbody&amp;gt;tr' ).find( 'td:eq(1)' ) );&lt;br /&gt;
				this.labels = this.labels.add( $( '.TablePager_col_img_name' ) );&lt;br /&gt;
				break;&lt;br /&gt;
			case 'gallery':&lt;br /&gt;
			// this.labels = this.labels.add( '.gallerybox' ); // TODO incombatible with GalleryDetails&lt;br /&gt;
				this.labels = this.labels.add( '.gallerytext' );&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	getTitleFromLink: function ( $a ) {&lt;br /&gt;
		try {&lt;br /&gt;
			return decodeURIComponent( $a.attr( 'href' ) )&lt;br /&gt;
				.match( /wiki\/(.+?)(?:#.+)?$/ )[ 1 ].replace( /_/g, ' ' );&lt;br /&gt;
		} catch ( ex ) {&lt;br /&gt;
			return '';&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
*  @brief Get title from selected pages&lt;br /&gt;
*  @return [array] touple of page title and $object&lt;br /&gt;
*/&lt;br /&gt;
	getMarkedLabels: function () {&lt;br /&gt;
		this.selectedLabels = this.labels.filter( '.cat_a_lot_selected:visible' );&lt;br /&gt;
		return this.selectedLabels.map( function () {&lt;br /&gt;
			var label = $( this ), file = label.find( 'a[title][class$=&amp;quot;title&amp;quot;]' );&lt;br /&gt;
			file = file.length ? file : label.find( 'a[title]' );&lt;br /&gt;
			var title = file.attr( 'title' ) ||&lt;br /&gt;
CAL.getTitleFromLink( file ) ||&lt;br /&gt;
CAL.getTitleFromLink( label.find( 'a' ) ) ||&lt;br /&gt;
CAL.getTitleFromLink( label.parent().find( 'a' ) ); // TODO needs optimization&lt;br /&gt;
			if ( title.indexOf( formattedNS[ 2 ] + ':' ) ) { return [ [ title, label ] ]; }&lt;br /&gt;
		} );&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	updateSelectionCounter: function () {&lt;br /&gt;
		this.selectedLabels = this.labels.filter( '.cat_a_lot_selected:visible' );&lt;br /&gt;
		var first = $markCounter.is( ':hidden' );&lt;br /&gt;
		$markCounter&lt;br /&gt;
			.html( msg( 'files-selected', this.selectedLabels.length ) )&lt;br /&gt;
			.show();&lt;br /&gt;
		if ( first &amp;amp;&amp;amp; !$dataContainer.is( ':hidden' ) ) { // Workaround to fix position glitch&lt;br /&gt;
			first = $markCounter.innerHeight();&lt;br /&gt;
			$container&lt;br /&gt;
				.offset( { top: $container.offset().top - first } )&lt;br /&gt;
				.height( $container.height() + first );&lt;br /&gt;
			$( window ).on( 'beforeunload', function () {&lt;br /&gt;
				if ( CAL.labels.filter( '.cat_a_lot_selected:visible' )[ 0 ] ) { return 'You have pages selected!'; } // There is a default message in the browser&lt;br /&gt;
			} );&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	makeClickable: function () {&lt;br /&gt;
		this.labels = $();&lt;br /&gt;
		this.pageLabels = $(); // only for distinct all selections&lt;br /&gt;
		this.findAllLabels( this.searchmode );&lt;br /&gt;
		this.labels.catALotShiftClick( function () {&lt;br /&gt;
			CAL.updateSelectionCounter();&lt;br /&gt;
		} )&lt;br /&gt;
			.addClass( 'cat_a_lot_label' );&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	toggleAll: function ( select ) {&lt;br /&gt;
		if ( typeof select === 'string' &amp;amp;&amp;amp; this.pageLabels[ 0 ] ) {&lt;br /&gt;
			this.pageLabels.toggleClass( 'cat_a_lot_selected', true );&lt;br /&gt;
			if ( select === 'files' ) // pages get deselected&lt;br /&gt;
			{ this.labels.toggleClass( 'cat_a_lot_selected' ); }&lt;br /&gt;
		} else {&lt;br /&gt;
		// invert / none / all&lt;br /&gt;
			this.labels.toggleClass( 'cat_a_lot_selected', select );&lt;br /&gt;
		}&lt;br /&gt;
		this.updateSelectionCounter();&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	getSubCats: function () {&lt;br /&gt;
		var data = {&lt;br /&gt;
			list: 'categorymembers',&lt;br /&gt;
			cmtype: 'subcat',&lt;br /&gt;
			cmlimit: this.settings.subcatcount,&lt;br /&gt;
			cmtitle: 'Category:' + this.currentCategory&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		this.doAPICall( data, function ( result ) {&lt;br /&gt;
			var cats = result.query.categorymembers;&lt;br /&gt;
			CAL.subCats = [];&lt;br /&gt;
			for ( var i = 0; i &amp;lt; cats.length; i++ ) { CAL.subCats.push( cats[ i ].title.replace( /^[^:]+:/, '' ) ); }&lt;br /&gt;
&lt;br /&gt;
			CAL.catCounter++;&lt;br /&gt;
			if ( CAL.catCounter === 2 ) { CAL.showCategoryList(); }&lt;br /&gt;
&lt;br /&gt;
		} );&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	getParentCats: function () {&lt;br /&gt;
		var data = {&lt;br /&gt;
			prop: 'categories',&lt;br /&gt;
			titles: 'Category:' + this.currentCategory&lt;br /&gt;
		};&lt;br /&gt;
		this.doAPICall( data, function ( result ) {&lt;br /&gt;
			CAL.parentCats = [];&lt;br /&gt;
			var cats,&lt;br /&gt;
				pages = result.query.pages,&lt;br /&gt;
				table = $( '&amp;lt;table&amp;gt;' );&lt;br /&gt;
&lt;br /&gt;
			if ( pages[ -1 ] &amp;amp;&amp;amp; pages[ -1 ].missing === '' ) {&lt;br /&gt;
				$resultList.html( '&amp;lt;span id=&amp;quot;cat_a_lot_no_found&amp;quot;&amp;gt;' + mw.msg( 'Categorytree-not-found', this.currentCategory ) + '&amp;lt;/span&amp;gt;' );&lt;br /&gt;
				document.body.style.cursor = 'auto';&lt;br /&gt;
				CAL.createCatLinks( '→', [ CAL.currentCategory ], table );&lt;br /&gt;
				$resultList.append( table );&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			// there should be only one, but we don't know its ID&lt;br /&gt;
			for ( var id in pages ) { cats = pages[ id ].categories || []; }&lt;br /&gt;
&lt;br /&gt;
			for ( var i = 0; i &amp;lt; cats.length; i++ ) { CAL.parentCats.push( cats[ i ].title.replace( /^[^:]+:/, '' ) ); }&lt;br /&gt;
&lt;br /&gt;
			CAL.catCounter++;&lt;br /&gt;
			if ( CAL.catCounter === 2 ) { CAL.showCategoryList(); }&lt;br /&gt;
&lt;br /&gt;
		} );&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	localizedRegex: function ( namespaceNumber, fallback ) {&lt;br /&gt;
	// Copied from HotCat, thanks Lupo.&lt;br /&gt;
		var wikiTextBlank = '[\\t _\\xA0\\u1680\\u180E\\u2000-\\u200A\\u2028\\u2029\\u202F\\u205F\\u3000]+';&lt;br /&gt;
		var wikiTextBlankRE = new RegExp( wikiTextBlank, 'g' );&lt;br /&gt;
		var createRegexStr = function ( name ) {&lt;br /&gt;
			if ( !name || !name.length ) { return ''; }&lt;br /&gt;
&lt;br /&gt;
			var regexName = '';&lt;br /&gt;
			for ( var i = 0; i &amp;lt; name.length; i++ ) {&lt;br /&gt;
				var ii = name[ i ];&lt;br /&gt;
				var ll = ii.toLowerCase();&lt;br /&gt;
				var ul = ii.toUpperCase();&lt;br /&gt;
				regexName += ( ll === ul ) ? ii : '[' + ll + ul + ']';&lt;br /&gt;
			}&lt;br /&gt;
			return regexName.replace( /([\\\^\$\.\?\*\+\(\)])/g, '\\$1' )&lt;br /&gt;
				.replace( wikiTextBlankRE, wikiTextBlank );&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		fallback = fallback.toLowerCase();&lt;br /&gt;
		var canonical = formattedNS[ namespaceNumber ].toLowerCase();&lt;br /&gt;
		var RegexString = createRegexStr( canonical );&lt;br /&gt;
		if ( fallback &amp;amp;&amp;amp; canonical !== fallback ) { RegexString += '|' + createRegexStr( fallback ); }&lt;br /&gt;
&lt;br /&gt;
		for ( var catName in nsIDs ) { if ( typeof catName === 'string' &amp;amp;&amp;amp; catName.toLowerCase() !== canonical &amp;amp;&amp;amp; catName.toLowerCase() !== fallback &amp;amp;&amp;amp; nsIDs[ catName ] === namespaceNumber ) { RegexString += '|' + createRegexStr( catName ); } }&lt;br /&gt;
&lt;br /&gt;
		return ( '(?:' + RegexString + ')' );&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	regexCatBuilder: function ( category ) {&lt;br /&gt;
		var catname = this.localizedRegex( 14, 'Category' );&lt;br /&gt;
&lt;br /&gt;
		// Build a regexp string for matching the given category:&lt;br /&gt;
		// trim leading/trailing whitespace and underscores&lt;br /&gt;
		category = category.replace( /^[\s_]+|[\s_]+$/g, '' );&lt;br /&gt;
&lt;br /&gt;
		// escape regexp metacharacters (= any ASCII punctuation except _)&lt;br /&gt;
		category = mw.RegExp.escape( category );&lt;br /&gt;
&lt;br /&gt;
		// any sequence of spaces and underscores should match any other&lt;br /&gt;
		category = category.replace( /[\s_]+/g, '[\\s_]+' );&lt;br /&gt;
&lt;br /&gt;
		// Make the first character case-insensitive:&lt;br /&gt;
		var first = category.substr( 0, 1 );&lt;br /&gt;
		if ( first.toUpperCase() !== first.toLowerCase() ) { category = '[' + first.toUpperCase() + first.toLowerCase() + ']' + category.substr( 1 ); }&lt;br /&gt;
&lt;br /&gt;
		// Compile it into a RegExp that matches MediaWiki category syntax (yeah, it looks ugly):&lt;br /&gt;
		// XXX: the first capturing parens are assumed to match the sortkey, if present, including the | but excluding the ]]&lt;br /&gt;
		return new RegExp( '\\[\\[[\\s_]*' + catname + '[\\s_]*:[\\s_]*' + category + '[\\s_]*(\\|[^\\]]*(?:\\][^\\]]+)*)?\\]\\]\\s*', 'g' );&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	getContent: function ( page, targetcat, mode ) {&lt;br /&gt;
		if ( !this.cancelled ) {&lt;br /&gt;
			this.doAPICall( {&lt;br /&gt;
				curtimestamp: 1,&lt;br /&gt;
				// meta: 'tokens',&lt;br /&gt;
				prop: 'revisions',&lt;br /&gt;
				rvprop: 'content|timestamp',&lt;br /&gt;
				titles: page[ 0 ]&lt;br /&gt;
			}, function ( result ) {&lt;br /&gt;
				CAL.editCategories( result, page, targetcat, mode );&lt;br /&gt;
			} );&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	getTargetCat: function ( pages, targetcat, mode ) {&lt;br /&gt;
		if ( !this.cancelled ) {&lt;br /&gt;
			this.doAPICall( {&lt;br /&gt;
				meta: 'tokens',&lt;br /&gt;
				prop: 'categories|categoryinfo',&lt;br /&gt;
				titles: 'Category:' + targetcat&lt;br /&gt;
			}, function ( result ) {&lt;br /&gt;
				if ( !result || !result.query ) { return; }&lt;br /&gt;
				CAL.edittoken = result.query.tokens.csrftoken;&lt;br /&gt;
				result = CAL._getPageQuery( result );&lt;br /&gt;
				CAL.checkTargetCat( result );&lt;br /&gt;
				for ( var i = 0; i &amp;lt; pages.length; i++ ) { CAL.getContent( pages[ i ], targetcat, mode ); }&lt;br /&gt;
&lt;br /&gt;
			} );&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	checkTargetCat: function ( page ) {&lt;br /&gt;
		var is_dab = false; // disambiguation&lt;br /&gt;
		var is_redir = typeof page.redirect === 'string'; // Hard redirect?&lt;br /&gt;
		if ( typeof page.missing === 'string' ) { return alert( mw.msg( 'Apifeatureusage-warnings', mw.msg( 'Categorytree-not-found', page.title ) ) ); }&lt;br /&gt;
		var cats = page.categories;&lt;br /&gt;
		this.is_hidden = page.categoryinfo &amp;amp;&amp;amp; typeof page.categoryinfo.hidden === 'string';&lt;br /&gt;
&lt;br /&gt;
		if ( !is_redir &amp;amp;&amp;amp; cats &amp;amp;&amp;amp; ( CAL.disambig_category || CAL.redir_category ) ) {&lt;br /&gt;
			for ( var c = 0; c &amp;lt; cats.length; c++ ) {&lt;br /&gt;
				var cat = cats[ c ].title;&lt;br /&gt;
				if ( cat ) { // Strip namespace prefix&lt;br /&gt;
					cat = cat.substring( cat.indexOf( ':' ) + 1 ).replace( /_/g, ' ' );&lt;br /&gt;
					if ( cat === CAL.disambig_category ) {&lt;br /&gt;
						is_dab = true; break;&lt;br /&gt;
					} else if ( cat === CAL.redir_category ) {&lt;br /&gt;
						is_redir = true; break;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if ( !is_redir &amp;amp;&amp;amp; !is_dab ) { return; }&lt;br /&gt;
		alert( mw.msg( 'Apifeatureusage-warnings', page.title + ' is a ' + CAL.disambig_category ) );&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	// Remove {{Uncategorized}} (also with comment). No need to replace it with anything.&lt;br /&gt;
	removeUncat: function ( text ) {&lt;br /&gt;
		return ( this.settings.uncat ? text.replace( /\{\{\s*[Uu]ncategorized\s*[^}]*\}\}\s*(&amp;lt;!--.*?--&amp;gt;\s*)?/, '' ) : text );&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	doCleanup: function ( text ) {&lt;br /&gt;
		return ( this.settings.docleanup ? text.replace( /\{\{\s*[Cc]heck categories\s*(\|?.*?)\}\}/, '' ) : text );&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	editCategories: function ( result, file, targetcat, mode ) {&lt;br /&gt;
		if ( !result || !result.query ) {&lt;br /&gt;
		// Happens on unstable wifi connections..&lt;br /&gt;
			this.connectionError.push( file[ 0 ] );&lt;br /&gt;
			this.updateCounter();&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		var otext,&lt;br /&gt;
			timestamp,&lt;br /&gt;
			page = CAL._getPageQuery( result );&lt;br /&gt;
		if ( page.ns === 2 ) { return; }&lt;br /&gt;
		var id = page.revisions[ 0 ],&lt;br /&gt;
			catNS = this.localCatName; // canonical cat-name&lt;br /&gt;
&lt;br /&gt;
		this.starttimestamp = result.curtimestamp;&lt;br /&gt;
		otext = id[ '*' ];&lt;br /&gt;
		timestamp = id.timestamp;&lt;br /&gt;
&lt;br /&gt;
		var sourcecat = this.origin;&lt;br /&gt;
		// Check if that file is already in that category&lt;br /&gt;
		if ( mode !== 'remove' &amp;amp;&amp;amp; this.regexCatBuilder( targetcat ).test( otext ) ) {&lt;br /&gt;
			// If the new cat is already there, just remove the old one&lt;br /&gt;
			if ( mode === 'move' ) {&lt;br /&gt;
				mode = 'remove';&lt;br /&gt;
				targetcat = sourcecat;&lt;br /&gt;
			} else {&lt;br /&gt;
				this.alreadyThere.push( file[ 0 ] );&lt;br /&gt;
				this.updateCounter();&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Text modification (following 3 functions are partialy taken from HotCat)&lt;br /&gt;
		var wikiTextBlankOrBidi = '[\\t _\\xA0\\u1680\\u180E\\u2000-\\u200B\\u200E\\u200F\\u2028-\\u202F\\u205F\\u3000]*';&lt;br /&gt;
		// Whitespace regexp for handling whitespace between link components. Including the horizontal tab, but not \n\r\f\v:&lt;br /&gt;
		// a link must be on one single line.&lt;br /&gt;
		// MediaWiki also removes Unicode bidi override characters in page titles (and namespace names) completely.&lt;br /&gt;
		// This is *not* handled, as it would require us to allow any of [\u200E\u200F\u202A-\u202E] between any two&lt;br /&gt;
		// characters inside a category link. It _could_ be done though... We _do_ handle strange spaces, including the&lt;br /&gt;
		// zero-width space \u200B, and bidi overrides between the components of a category link (adjacent to the colon,&lt;br /&gt;
		// or adjacent to and inside of &amp;quot;[[&amp;quot; and &amp;quot;]]&amp;quot;).&lt;br /&gt;
		var findCatsRE = new RegExp( '\\[\\[' + wikiTextBlankOrBidi + this.localizedRegex( 14, 'Category' ) + wikiTextBlankOrBidi + ':[^\\]]+\\]\\]', 'g' );&lt;br /&gt;
&lt;br /&gt;
		function replaceByBlanks( match ) {&lt;br /&gt;
			return match.replace( /(\s|\S)/g, ' ' ); // /./ doesn't match linebreaks. /(\s|\S)/ does.&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		function find_insertionpoint( wikitext ) {&lt;br /&gt;
			var copiedtext = wikitext&lt;br /&gt;
				.replace( /&amp;lt;!--(\s|\S)*?--&amp;gt;/g, replaceByBlanks )&lt;br /&gt;
				.replace( /&amp;lt;nowiki&amp;gt;(\s|\S)*?&amp;lt;\/nowiki&amp;gt;/g, replaceByBlanks );&lt;br /&gt;
			// Search in copiedtext to avoid that we insert inside an HTML comment or a nowiki &amp;quot;element&amp;quot;.&lt;br /&gt;
			var index = -1;&lt;br /&gt;
			findCatsRE.lastIndex = 0;&lt;br /&gt;
			while ( findCatsRE.exec( copiedtext ) !== null ) { index = findCatsRE.lastIndex; }&lt;br /&gt;
&lt;br /&gt;
			return index;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/**&lt;br /&gt;
*  @brief Adds the new Category by searching the right insert point,&lt;br /&gt;
*         if there is text after the category section&lt;br /&gt;
*  @param [string] wikitext&lt;br /&gt;
*  @param [string] toAdd&lt;br /&gt;
*  @return Return wikitext&lt;br /&gt;
*/&lt;br /&gt;
		function addCategory( wikitext, toAdd ) {&lt;br /&gt;
			if ( toAdd &amp;amp;&amp;amp; toAdd[ 0 ] ) {&lt;br /&gt;
			// TODO: support sort key&lt;br /&gt;
				var cat_point = find_insertionpoint( wikitext ); // Position of last category&lt;br /&gt;
				var newcatstring = '[[' + catNS + toAdd + ']]';&lt;br /&gt;
				if ( cat_point &amp;gt; -1 ) {&lt;br /&gt;
					var suffix = wikitext.substring( cat_point );&lt;br /&gt;
					wikitext = wikitext.substring( 0, cat_point ) + ( cat_point ? '\n' : '' ) + newcatstring;&lt;br /&gt;
					if ( suffix[ 0 ] &amp;amp;&amp;amp; suffix.substr( 0, 1 ) !== '\n' ) { wikitext += '\n'; }&lt;br /&gt;
					wikitext += suffix;&lt;br /&gt;
				} else {&lt;br /&gt;
					if ( wikitext[ 0 ] &amp;amp;&amp;amp; wikitext.substr( wikitext.length - 1, 1 ) !== '\n' ) { wikitext += '\n'; }&lt;br /&gt;
&lt;br /&gt;
					wikitext += ( wikitext[ 0 ] ? '\n' : '' ) + newcatstring;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return wikitext;&lt;br /&gt;
		}&lt;br /&gt;
		// End HotCat functions&lt;br /&gt;
&lt;br /&gt;
		var text = otext,&lt;br /&gt;
			arr = is_rtl ? '\u2190' : '\u2192', // left and right arrows. Don't use ← and → in the code.&lt;br /&gt;
			sumCmt, // summary comment&lt;br /&gt;
			sumCmtShort;&lt;br /&gt;
		// Fix text&lt;br /&gt;
		switch ( mode ) {&lt;br /&gt;
			case 'add':&lt;br /&gt;
				text = addCategory( text, targetcat );&lt;br /&gt;
				sumCmt = msg( 'summary-add' ).replace( /\$1/g, targetcat );&lt;br /&gt;
				sumCmtShort = '+[[' + catNS + targetcat + ']]';&lt;br /&gt;
				break;&lt;br /&gt;
			case 'copy':&lt;br /&gt;
				text = text.replace( this.regexCatBuilder( sourcecat ), '[[' + catNS + sourcecat + '$1]]\n[[' + catNS + targetcat + '$1]]\n' );&lt;br /&gt;
				sumCmt = msg( 'summary-copy' ).replace( /\$1/g, sourcecat ).replace( /\$2/g, targetcat );&lt;br /&gt;
				sumCmtShort = '+[[' + catNS + sourcecat + ']]' + arr + '[[' + catNS + targetcat + ']]';&lt;br /&gt;
				// If category is added through template:&lt;br /&gt;
				if ( otext === text ) { text = addCategory( text, targetcat ); }&lt;br /&gt;
&lt;br /&gt;
				break;&lt;br /&gt;
			case 'move':&lt;br /&gt;
				text = text.replace( this.regexCatBuilder( sourcecat ), '[[' + catNS + targetcat + '$1]]\n' );&lt;br /&gt;
				sumCmt = msg( 'summary-move' ).replace( /\$1/g, sourcecat ).replace( /\$2/g, targetcat );&lt;br /&gt;
				sumCmtShort = '±[[' + catNS + sourcecat + ']]' + arr + '[[' + catNS + targetcat + ']]';&lt;br /&gt;
				break;&lt;br /&gt;
			case 'remove':&lt;br /&gt;
				text = text.replace( this.regexCatBuilder( targetcat ), '' );&lt;br /&gt;
				sumCmt = msg( 'summary-remove' ).replace( /\$1/g, targetcat );&lt;br /&gt;
				sumCmtShort = '-[[' + catNS + targetcat + ']]';&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if ( text === otext ) {&lt;br /&gt;
			this.notFound.push( file[ 0 ] );&lt;br /&gt;
			this.updateCounter();&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		otext = text;&lt;br /&gt;
&lt;br /&gt;
		// Remove {{uncat}} after we checked whether we changed the text successfully.&lt;br /&gt;
		// Otherwise we might fail to do the changes, but still replace {{uncat}}&lt;br /&gt;
		if ( mode !== 'remove' &amp;amp;&amp;amp; ( !non || userGrp.indexOf( 'autoconfirmed' ) &amp;gt; -1 ) ) {&lt;br /&gt;
			if ( !this.is_hidden ) {&lt;br /&gt;
				text = this.removeUncat( text );&lt;br /&gt;
				if ( text.length !== otext.length ) { sumCmt += '; ' + msg( 'uncatpref' ); }&lt;br /&gt;
			}&lt;br /&gt;
			text = this.doCleanup( text );&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		sumCmt += this.summary ? ' ' + this.summary : '';&lt;br /&gt;
&lt;br /&gt;
		var preM = msg( 'prefix-summary' );&lt;br /&gt;
		var usgM = msg( 'using-summary' );&lt;br /&gt;
		// Try shorten summary&lt;br /&gt;
		if ( preM || usgM )	{&lt;br /&gt;
			sumCmt = ( sumCmt.length &amp;gt; 250 - preM.length - usgM.length ) ?&lt;br /&gt;
				sumCmt + ' (CatAlot)' : preM + sumCmt + usgM;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if ( sumCmt.length &amp;gt; 254 ) // Try short summary&lt;br /&gt;
		{ sumCmt = sumCmtShort; }&lt;br /&gt;
&lt;br /&gt;
		var data = {&lt;br /&gt;
			action: 'edit',&lt;br /&gt;
			assert: 'user',&lt;br /&gt;
			summary: sumCmt,&lt;br /&gt;
			title: file[ 0 ],&lt;br /&gt;
			text: text,&lt;br /&gt;
			bot: true,&lt;br /&gt;
			starttimestamp: this.starttimestamp,&lt;br /&gt;
			basetimestamp: timestamp,&lt;br /&gt;
			watchlist: this.settings.watchlist,&lt;br /&gt;
			minor: this.settings.minor,&lt;br /&gt;
			tags: this.changeTag,&lt;br /&gt;
			token: this.edittoken&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		this.doAPICall( data, function ( r ) {&lt;br /&gt;
			delete CAL.XHR[ file[ 0 ] ];&lt;br /&gt;
			return CAL.updateUndoCounter( r );&lt;br /&gt;
		} );&lt;br /&gt;
		this.markAsDone( file[ 1 ], mode, targetcat );&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	markAsDone: function ( label, mode, targetcat ) {&lt;br /&gt;
		mode = ( function ( m ) {&lt;br /&gt;
			switch ( m ) {&lt;br /&gt;
				case 'add': return 'added-cat';&lt;br /&gt;
				case 'copy': return 'copied-cat';&lt;br /&gt;
				case 'move': return 'moved-cat';&lt;br /&gt;
				case 'remove': return 'removed-cat';&lt;br /&gt;
			}&lt;br /&gt;
		}( mode ) );&lt;br /&gt;
		label.addClass( 'cat_a_lot_markAsDone' ).append( '&amp;lt;br&amp;gt;' + msg( mode, targetcat ) );&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	updateUndoCounter: function ( r ) {&lt;br /&gt;
		this.updateCounter();&lt;br /&gt;
		if ( !r.edit || r.edit.result !== 'Success' ) { return; }&lt;br /&gt;
		r = r.edit;&lt;br /&gt;
&lt;br /&gt;
		this.undoList.push( {&lt;br /&gt;
			title: r.title,&lt;br /&gt;
			id: r.newrevid,&lt;br /&gt;
			timestamp: r.newtimestamp&lt;br /&gt;
		} );&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	updateCounter: function () {&lt;br /&gt;
		this.counterCurrent++;&lt;br /&gt;
		if ( this.counterCurrent &amp;gt; this.counterNeeded ) { this.displayResult(); } else { this.domCounter.text( this.counterCurrent ); }&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	displayResult: function () {&lt;br /&gt;
		document.body.style.cursor = 'auto';&lt;br /&gt;
		$.removeSpinner( 'fb-dialog' );&lt;br /&gt;
		this.progressDialog.parent()&lt;br /&gt;
			.addClass( 'cat_a_lot_done' )&lt;br /&gt;
			.find( '.ui-dialog-buttonpane button span' ).eq( 0 )&lt;br /&gt;
			.text( mw.msg( 'Mobile-frontend-return-to-page' ) );&lt;br /&gt;
		var rep = this.domCounter.parent()&lt;br /&gt;
			.height( 'auto' )&lt;br /&gt;
			.html( '&amp;lt;h3&amp;gt;' + msg( 'done' ) + '&amp;lt;/h3&amp;gt;' )&lt;br /&gt;
			.append( msg( 'all-done' ) + '&amp;lt;br&amp;gt;' );&lt;br /&gt;
		if ( this.alreadyThere.length ) {&lt;br /&gt;
			rep.append( '&amp;lt;h5&amp;gt;' + msg( 'skipped-already', this.alreadyThere.length ) + '&amp;lt;/h5&amp;gt;' )&lt;br /&gt;
				.append( this.alreadyThere.join( '&amp;lt;br&amp;gt;' ) );&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if ( this.notFound.length ) {&lt;br /&gt;
			rep.append( '&amp;lt;h5&amp;gt;' + msg( 'skipped-not-found', this.notFound.length ) + '&amp;lt;/h5&amp;gt;' )&lt;br /&gt;
				.append( this.notFound.join( '&amp;lt;br&amp;gt;' ) );&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if ( this.connectionError.length ) {&lt;br /&gt;
			rep.append( '&amp;lt;h5&amp;gt;' + msg( 'skipped-server', this.connectionError.length ) + '&amp;lt;/h5&amp;gt;' )&lt;br /&gt;
				.append( this.connectionError.join( '&amp;lt;br&amp;gt;' ) );&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
*  @brief set parameters for API call,&lt;br /&gt;
*  	convert targetcat to string, get selected pages/files&lt;br /&gt;
*  @param [dom object] targetcat with data&lt;br /&gt;
*  @param [string] mode action&lt;br /&gt;
*  @return Return API call getTargetCat with pages&lt;br /&gt;
*/&lt;br /&gt;
	doSomething: function ( targetcat, mode ) {&lt;br /&gt;
		var pages = this.getMarkedLabels();&lt;br /&gt;
		if ( !pages.length ) { return alert( mw.msg( 'Ooui-selectfile-placeholder' ) ); }&lt;br /&gt;
		targetcat = $( targetcat ).closest( 'tr' ).data( 'cat' );&lt;br /&gt;
&lt;br /&gt;
		this.notFound = [];&lt;br /&gt;
		this.alreadyThere = [];&lt;br /&gt;
		this.connectionError = [];&lt;br /&gt;
		this.counterCurrent = 1;&lt;br /&gt;
		this.counterNeeded = pages.length;&lt;br /&gt;
		this.undoList = [];&lt;br /&gt;
		this.XHR = {};&lt;br /&gt;
		this.cancelled = 0;&lt;br /&gt;
		this.summary = '';&lt;br /&gt;
&lt;br /&gt;
		if ( $( '#cat_a_lot_comment' ).prop( 'checked' ) ) { this.summary = window.prompt( msg( 'edit-question' ), '' ); } // TODO custom pre-value&lt;br /&gt;
		if ( this.summary !== null ) {&lt;br /&gt;
			mw.loader.using( [ 'jquery.ui.dialog', 'jquery.spinner', 'mediawiki.RegExp' ], function () {&lt;br /&gt;
				CAL.showProgress();&lt;br /&gt;
				CAL.getTargetCat( pages, targetcat, mode );&lt;br /&gt;
			} );&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	doAPICall: function ( params, callback ) {&lt;br /&gt;
		params = $.extend( {&lt;br /&gt;
			action: 'query',&lt;br /&gt;
			format: 'json'&lt;br /&gt;
		}, params );&lt;br /&gt;
&lt;br /&gt;
		var i = 0,&lt;br /&gt;
			apiUrl = this.apiUrl,&lt;br /&gt;
			doCall,&lt;br /&gt;
			handleError = function ( jqXHR, textStatus, errorThrown ) {&lt;br /&gt;
				mw.log( 'Error: ', jqXHR, textStatus, errorThrown );&lt;br /&gt;
				if ( i &amp;lt; 4 ) {&lt;br /&gt;
					window.setTimeout( doCall, 300 );&lt;br /&gt;
					i++;&lt;br /&gt;
				} else if ( params.title ) {&lt;br /&gt;
					this.connectionError.push( params.title );&lt;br /&gt;
					this.updateCounter();&lt;br /&gt;
					return;&lt;br /&gt;
				}&lt;br /&gt;
			};&lt;br /&gt;
		doCall = function () {&lt;br /&gt;
			var xhr = $.ajax( {&lt;br /&gt;
				url: apiUrl,&lt;br /&gt;
				cache: false,&lt;br /&gt;
				dataType: 'json',&lt;br /&gt;
				data: params,&lt;br /&gt;
				type: 'POST',&lt;br /&gt;
				success: callback,&lt;br /&gt;
				error: handleError&lt;br /&gt;
			} );&lt;br /&gt;
&lt;br /&gt;
			if ( params.action === 'edit' &amp;amp;&amp;amp; !CAL.cancelled ) { CAL.XHR[ params.title ] = xhr; }&lt;br /&gt;
		};&lt;br /&gt;
		doCall();&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	createCatLinks: function ( symbol, list, table ) {&lt;br /&gt;
		list.sort();&lt;br /&gt;
		var button = ( this.settings.button &amp;amp;&amp;amp; mw.loader.getState( 'jquery.ui.button' ) === 'ready' ) ? 1 : 0;&lt;br /&gt;
		for ( var c = 0; c &amp;lt; list.length; c++ ) {&lt;br /&gt;
			var $tr = $( '&amp;lt;tr&amp;gt;' ),&lt;br /&gt;
				$link = $( '&amp;lt;a&amp;gt;', {&lt;br /&gt;
					href: mw.util.getUrl( CAL.localCatName + list[ c ] ),&lt;br /&gt;
					text: list[ c ]&lt;br /&gt;
				} ),&lt;br /&gt;
				$buttons = [];&lt;br /&gt;
			$tr.data( 'cat', list[ c ] );&lt;br /&gt;
			$link.on( 'click', function ( e ) {&lt;br /&gt;
				if ( !e.ctrlKey ) {&lt;br /&gt;
					e.preventDefault();&lt;br /&gt;
					CAL.updateCats( $( this ).closest( 'tr' ).data( 'cat' ) );&lt;br /&gt;
				}&lt;br /&gt;
			} );&lt;br /&gt;
&lt;br /&gt;
			$tr.append( $( '&amp;lt;td&amp;gt;' ).text( symbol ) )&lt;br /&gt;
				.append( $( '&amp;lt;td&amp;gt;' ).append( $link ) );&lt;br /&gt;
&lt;br /&gt;
			$buttons.push( $( '&amp;lt;a&amp;gt;' )&lt;br /&gt;
				.text( mw.msg( 'Centralnotice-remove' ) )&lt;br /&gt;
				.on( 'click', function () {&lt;br /&gt;
					CAL.doSomething( this, 'remove' );&lt;br /&gt;
				} )&lt;br /&gt;
				.addClass( 'cat_a_lot_move' )&lt;br /&gt;
			);&lt;br /&gt;
			if ( button ) {&lt;br /&gt;
				$buttons.slice( -1 )[ 0 ].button( {&lt;br /&gt;
					icons: { primary: 'ui-icon-minusthick' },&lt;br /&gt;
					showLabel: false,&lt;br /&gt;
					text: false&lt;br /&gt;
				} );&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			if ( this.origin ) {&lt;br /&gt;
			// Can't move to source category&lt;br /&gt;
				if ( list[ c ] !== this.origin ) {&lt;br /&gt;
					$buttons.push( $( '&amp;lt;a&amp;gt;' )&lt;br /&gt;
						.text( msg( 'move' ) )&lt;br /&gt;
						.on( 'click', function () {&lt;br /&gt;
							CAL.doSomething( this, 'move' );&lt;br /&gt;
						} )&lt;br /&gt;
						.addClass( 'cat_a_lot_move' )&lt;br /&gt;
					);&lt;br /&gt;
					if ( button ) {&lt;br /&gt;
						$buttons.slice( -1 )[ 0 ].button( {&lt;br /&gt;
							icons: { primary: 'ui-icon-arrowthick-1-e' },&lt;br /&gt;
							showLabel: false,&lt;br /&gt;
							text: false&lt;br /&gt;
						} );&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					$buttons.push( $( '&amp;lt;a&amp;gt;' )&lt;br /&gt;
						.text( msg( 'copy' ) )&lt;br /&gt;
						.on( 'click', function () {&lt;br /&gt;
							CAL.doSomething( this, 'copy' );&lt;br /&gt;
						} )&lt;br /&gt;
						.addClass( 'cat_a_lot_action' )&lt;br /&gt;
					);&lt;br /&gt;
					if ( button ) {&lt;br /&gt;
						$buttons.slice( -1 )[ 0 ].button( {&lt;br /&gt;
							icons: { primary: 'ui-icon-plusthick' },&lt;br /&gt;
							showLabel: false,&lt;br /&gt;
							text: false&lt;br /&gt;
						} );&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			} else {&lt;br /&gt;
				$buttons.push( $( '&amp;lt;a&amp;gt;' )&lt;br /&gt;
					.text( msg( 'add' ) )&lt;br /&gt;
					.on( 'click', function () {&lt;br /&gt;
						CAL.doSomething( this, 'add' );&lt;br /&gt;
					} )&lt;br /&gt;
					.addClass( 'cat_a_lot_action' )&lt;br /&gt;
				);&lt;br /&gt;
				if ( button ) {&lt;br /&gt;
					$buttons.slice( -1 )[ 0 ].button( {&lt;br /&gt;
						icons: { primary: 'ui-icon-plusthick' },&lt;br /&gt;
						showLabel: false,&lt;br /&gt;
						text: false&lt;br /&gt;
					} );&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
			}&lt;br /&gt;
			// TODO CSS may extern&lt;br /&gt;
			var css = button ? { fontSize: '.6em', margin: '0', width: '2.5em' } : {};&lt;br /&gt;
			for ( var b = 0; b &amp;lt; $buttons.length; b++ ) { $tr.append( $( '&amp;lt;td&amp;gt;' ).append( $buttons[ b ].css( css ) ) ); }&lt;br /&gt;
&lt;br /&gt;
			table.append( $tr );&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	getCategoryList: function () {&lt;br /&gt;
		this.catCounter = 0;&lt;br /&gt;
		this.getParentCats();&lt;br /&gt;
		this.getSubCats();&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	_getPageQuery: function ( data ) {&lt;br /&gt;
	// There should be only one, but we don't know its ID&lt;br /&gt;
		if ( data &amp;amp;&amp;amp; data.query &amp;amp;&amp;amp; data.query.pages ) {&lt;br /&gt;
			data = data.query.pages;&lt;br /&gt;
			for ( var p in data ) { return data[ p ]; }&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
*  @brief takes this.currentCategory if redir_category is configured&lt;br /&gt;
** Cat pages with more than one cat link are still not supported for sure&lt;br /&gt;
*  @return soft redirected cat&lt;br /&gt;
*/&lt;br /&gt;
	solveSoftRedirect: function () {&lt;br /&gt;
		this.doAPICall( {&lt;br /&gt;
			prop: 'links', // TODO: For more accuracy the revisions could be checked&lt;br /&gt;
			titles: 'Category:' + this.currentCategory,&lt;br /&gt;
			// 'rvprop': 'content',&lt;br /&gt;
			// 'pllimit': 'max',&lt;br /&gt;
			plnamespace: 14&lt;br /&gt;
		}, function ( page ) {&lt;br /&gt;
			page = CAL._getPageQuery( page );&lt;br /&gt;
			if ( page ) {&lt;br /&gt;
				var lks = page.links;&lt;br /&gt;
				if ( lks &amp;amp;&amp;amp; lks.length === 1 &amp;amp;&amp;amp; lks[ 0 ].title ) {&lt;br /&gt;
					CAL.currentCategory = lks[ 0 ].title.replace( reCat, '' );&lt;br /&gt;
					$searchInput.val( CAL.currentCategory );&lt;br /&gt;
					return CAL.getCategoryList();&lt;br /&gt;
				} else {&lt;br /&gt;
				// TODO? better translatable warning message: &amp;quot;Please solve the category soft redirect manually!&amp;quot;&lt;br /&gt;
					$resultList.html( '&amp;lt;span id=&amp;quot;cat_a_lot_no_found&amp;quot;&amp;gt;' + mw.msg( 'Apifeatureusage-warnings', mw.msg( 'Categorytree-not-found', CAL.currentCategory ) ) + '&amp;lt;/span&amp;gt;' );&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		} );&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	showCategoryList: function () {&lt;br /&gt;
		if ( this.settings.redir_category &amp;amp;&amp;amp; this.settings.redir_category === this.parentCats[ 0 ] ) { return this.solveSoftRedirect(); }&lt;br /&gt;
&lt;br /&gt;
		var table = $( '&amp;lt;table&amp;gt;' );&lt;br /&gt;
&lt;br /&gt;
		this.createCatLinks( '↑', this.parentCats, table );&lt;br /&gt;
		this.createCatLinks( '→', [ this.currentCategory ], table );&lt;br /&gt;
		// Show on soft-redirect&lt;br /&gt;
		if ( $searchInput.val() === this.currentCategory &amp;amp;&amp;amp; this.origin !== this.currentCategory ) { this.createCatLinks( '→', [ this.origin ], table ); }&lt;br /&gt;
		this.createCatLinks( '↓', this.subCats, table );&lt;br /&gt;
&lt;br /&gt;
		$resultList.empty();&lt;br /&gt;
		$resultList.append( table );&lt;br /&gt;
&lt;br /&gt;
		document.body.style.cursor = 'auto';&lt;br /&gt;
&lt;br /&gt;
		// Reset width&lt;br /&gt;
		$container.width( '' );&lt;br /&gt;
		$container.height( '' );&lt;br /&gt;
		$container.width( Math.min( table.width() * 1.1 + 15, $( window ).width() - 10 ) );&lt;br /&gt;
&lt;br /&gt;
		$resultList.css( {&lt;br /&gt;
			maxHeight: Math.min( this.setHeight, $( window ).height() - $container.position().top - $settingsLink.outerHeight() - $selections.outerHeight() - 15 ),&lt;br /&gt;
			height: ''&lt;br /&gt;
		} );&lt;br /&gt;
		table.width( '100%' );&lt;br /&gt;
		$container.height( Math.min( $container.height(), $head.offset().top - $container.offset().top + 10 ) );&lt;br /&gt;
		$container.offset( { left: $( window ).width() - $container.outerWidth() } ); // Fix overlap&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	updateCats: function ( newcat ) {&lt;br /&gt;
		document.body.style.cursor = 'wait';&lt;br /&gt;
		this.currentCategory = newcat;&lt;br /&gt;
		$resultList.html( '&amp;lt;div class=&amp;quot;cat_a_lot_loading&amp;quot;&amp;gt;' + mw.msg( 'Wikieditor-loading' ) + '&amp;lt;/div&amp;gt;' );&lt;br /&gt;
		this.getCategoryList();&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	doUndo: function () {&lt;br /&gt;
		this.cancelled = 0;&lt;br /&gt;
		this.doAbort();&lt;br /&gt;
		if ( !this.undoList.length ) { return; }&lt;br /&gt;
&lt;br /&gt;
		$( '.cat_a_lot_feedback' ).removeClass( 'cat_a_lot_done' );&lt;br /&gt;
		this.counterNeeded = this.undoList.length;&lt;br /&gt;
		this.counterCurrent = 1;&lt;br /&gt;
&lt;br /&gt;
		document.body.style.cursor = 'wait';&lt;br /&gt;
&lt;br /&gt;
		var query = {&lt;br /&gt;
			action: 'edit',&lt;br /&gt;
			user: mw.config.get( 'wgUserName' ),&lt;br /&gt;
			bot: true,&lt;br /&gt;
			minor: this.settings.minor,&lt;br /&gt;
			starttimestamp: this.starttimestamp,&lt;br /&gt;
			watchlist: this.settings.watchlist,&lt;br /&gt;
			tags: this.changeTag,&lt;br /&gt;
			token: this.edittoken&lt;br /&gt;
		};&lt;br /&gt;
		for ( var i = 0; i &amp;lt; this.undoList.length; i++ ) {&lt;br /&gt;
			var uID = this.undoList[ i ];&lt;br /&gt;
			query.title = uID.title;&lt;br /&gt;
			query.undo = uID.id;&lt;br /&gt;
			query.basetimestamp = uID.timestamp;&lt;br /&gt;
			this.doAPICall( query, function ( r ) {&lt;br /&gt;
			// TODO: Add &amp;quot;details&amp;quot; to progressbar?&lt;br /&gt;
			// $resultList.append( [mw.msg('Filerevert-submit') + &amp;quot; done &amp;quot; + r.edit.title, '&amp;lt;br&amp;gt;' ] );&lt;br /&gt;
				if ( r &amp;amp;&amp;amp; r.edit ) { mw.log( 'Revert done', r.edit.title ); }&lt;br /&gt;
				CAL.updateCounter();&lt;br /&gt;
			} );&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	doAbort: function () {&lt;br /&gt;
		for ( var t in this.XHR ) { this.XHR[ t ].abort(); }&lt;br /&gt;
&lt;br /&gt;
		if ( this.cancelled ) { // still not for undo&lt;br /&gt;
			this.progressDialog.remove();&lt;br /&gt;
			this.toggleAll( false );&lt;br /&gt;
			$head.last().show();&lt;br /&gt;
		}&lt;br /&gt;
		this.cancelled = 1;&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	showProgress: function () {&lt;br /&gt;
		document.body.style.cursor = 'wait';&lt;br /&gt;
		this.progressDialog = $( '&amp;lt;div&amp;gt;' )&lt;br /&gt;
			.html( ' ' + msg( 'editing' ) + ' &amp;lt;span id=&amp;quot;cat_a_lot_current&amp;quot;&amp;gt;' + CAL.counterCurrent + '&amp;lt;/span&amp;gt; ' + msg( 'of' ) + CAL.counterNeeded )&lt;br /&gt;
			.prepend( $.createSpinner( { id: 'fb-dialog', size: 'large' } ) )&lt;br /&gt;
			.dialog( {&lt;br /&gt;
				width: 450,&lt;br /&gt;
				height: 180,&lt;br /&gt;
				minHeight: 90,&lt;br /&gt;
				modal: true,&lt;br /&gt;
				resizable: false,&lt;br /&gt;
				draggable: false,&lt;br /&gt;
				// closeOnEscape: true,&lt;br /&gt;
				dialogClass: 'cat_a_lot_feedback',&lt;br /&gt;
				buttons: [ {&lt;br /&gt;
					text: mw.msg( 'Cancel' ), // Stops all actions&lt;br /&gt;
					click: function () {&lt;br /&gt;
						$( this ).dialog( 'close' );&lt;br /&gt;
					}&lt;br /&gt;
				} ],&lt;br /&gt;
				close: function () {&lt;br /&gt;
					CAL.cancelled = 1;&lt;br /&gt;
					CAL.doAbort();&lt;br /&gt;
					$( this ).remove();&lt;br /&gt;
				},&lt;br /&gt;
				open: function ( event, ui ) { // Workaround modify&lt;br /&gt;
					ui = $( this ).parent();&lt;br /&gt;
					ui.find( '.ui-dialog-titlebar' ).hide();&lt;br /&gt;
					ui.find( '.ui-dialog-buttonpane.ui-widget-content' )&lt;br /&gt;
						.removeClass( 'ui-widget-content' );&lt;br /&gt;
				/* .find( 'span' ).css( { fontSize: '90%' } )*/&lt;br /&gt;
				}&lt;br /&gt;
			} );&lt;br /&gt;
		if ( $head.children().length &amp;lt; 3 ) {&lt;br /&gt;
			$( '&amp;lt;span&amp;gt;' )&lt;br /&gt;
				.css( {&lt;br /&gt;
					'float': 'right',&lt;br /&gt;
					fontSize: '75%'&lt;br /&gt;
				} )&lt;br /&gt;
				.append( [ '[ ',&lt;br /&gt;
					$( '&amp;lt;a&amp;gt;', { title: 'Revert all last done edits' } ) // TODO i18n&lt;br /&gt;
						.on( 'click', function () {&lt;br /&gt;
							if ( window.confirm( mw.msg( 'Apifeatureusage-warnings', this.title + '⁉' ) ) ) {&lt;br /&gt;
								CAL.doUndo();&lt;br /&gt;
								$( this ).parent().remove();&lt;br /&gt;
							}&lt;br /&gt;
							return false;&lt;br /&gt;
						} )&lt;br /&gt;
						.addClass( 'new' )&lt;br /&gt;
						.text( mw.msg( 'Filerevert-submit' ) ),&lt;br /&gt;
					' ]'&lt;br /&gt;
				] ).insertAfter( $link );&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		this.domCounter = $( '#cat_a_lot_current' );&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	minimize: function ( e ) {&lt;br /&gt;
		CAL.top = Math.max( 0, $container.position().top );&lt;br /&gt;
		CAL.height = $container.height();&lt;br /&gt;
		$dataContainer.hide();&lt;br /&gt;
		$container.animate( {&lt;br /&gt;
			height: $head.height(),&lt;br /&gt;
			top: $( window ).height() - $head.height() * 1.4&lt;br /&gt;
		}, function () {&lt;br /&gt;
			$( e.target ).one( 'click', CAL.maximize );&lt;br /&gt;
		} );&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	maximize: function ( e ) {&lt;br /&gt;
		$dataContainer.show();&lt;br /&gt;
		$container.animate( {&lt;br /&gt;
			top: CAL.top,&lt;br /&gt;
			height: CAL.height&lt;br /&gt;
		}, function () {&lt;br /&gt;
			$( e.target ).one( 'click', CAL.minimize );&lt;br /&gt;
		} );&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	run: function () {&lt;br /&gt;
		if ( $( '.cat_a_lot_enabled' )[ 0 ] ) {&lt;br /&gt;
			this.makeClickable();&lt;br /&gt;
			if ( !this.executed ) { // only once&lt;br /&gt;
				$selectInvert.text( mw.msg( 'Checkbox-invert' ) );&lt;br /&gt;
				if ( this.settings.editpages &amp;amp;&amp;amp; this.pageLabels[ 0 ] ) {&lt;br /&gt;
					$selectFiles.text( mw.msg( 'Prefs-files' ) );&lt;br /&gt;
					$selectPages.text( mw.msg( 'Categories' ) ).parent().show();&lt;br /&gt;
				}&lt;br /&gt;
				$link.after( $( '&amp;lt;a&amp;gt;' )&lt;br /&gt;
					.text( '–' )&lt;br /&gt;
					.css( { fontWeight: 'bold', marginLeft: '.7em' } )&lt;br /&gt;
					.one( 'click', this.minimize )&lt;br /&gt;
				);&lt;br /&gt;
			}&lt;br /&gt;
			$dataContainer.show();&lt;br /&gt;
			$container.one( 'mouseover', function () {&lt;br /&gt;
				$( this )&lt;br /&gt;
					.resizable( {&lt;br /&gt;
						handles: 'n',&lt;br /&gt;
						alsoResize: '#cat_a_lot_category_list',&lt;br /&gt;
						resize: function () {&lt;br /&gt;
							$resultList&lt;br /&gt;
								.css( {&lt;br /&gt;
									maxHeight: '',&lt;br /&gt;
									width: ''&lt;br /&gt;
								} );&lt;br /&gt;
						},&lt;br /&gt;
						start: function ( e, ui ) { // Otherwise box get static if sametime resize with draggable&lt;br /&gt;
							ui.helper.css( {&lt;br /&gt;
								top: ui.helper.offset().top - $( window ).scrollTop(),&lt;br /&gt;
								position: 'fixed'&lt;br /&gt;
							} );&lt;br /&gt;
						},&lt;br /&gt;
						stop: function () {&lt;br /&gt;
							CAL.setHeight = $resultList.height();&lt;br /&gt;
						}&lt;br /&gt;
					} )&lt;br /&gt;
					.draggable( {&lt;br /&gt;
						cursor: 'move',&lt;br /&gt;
						start: function ( e, ui ) {&lt;br /&gt;
							ui.helper.on( 'click.prevent',&lt;br /&gt;
								function ( e ) { e.preventDefault(); }&lt;br /&gt;
							);&lt;br /&gt;
							ui.helper.css( 'height', ui.helper.height() );&lt;br /&gt;
						},&lt;br /&gt;
						stop: function ( e, ui ) {&lt;br /&gt;
							setTimeout(&lt;br /&gt;
								function () {&lt;br /&gt;
									ui.helper.off( 'click.prevent' );&lt;br /&gt;
								}, 300&lt;br /&gt;
							);&lt;br /&gt;
						}&lt;br /&gt;
					} )&lt;br /&gt;
					.one( 'mousedown', function () {&lt;br /&gt;
						$container.height( $container.height() ); // Workaround to calculate&lt;br /&gt;
					} );&lt;br /&gt;
				$resultList&lt;br /&gt;
					.css( { maxHeight: 450 } );&lt;br /&gt;
			} );&lt;br /&gt;
			this.updateCats( this.origin || 'Images' );&lt;br /&gt;
&lt;br /&gt;
			$link.html( $( '&amp;lt;span&amp;gt;' )&lt;br /&gt;
				.text( '×' )&lt;br /&gt;
				.css( { font: 'bold 2em monospace', lineHeight: '.75em' } )&lt;br /&gt;
			);&lt;br /&gt;
			$link.next().show();&lt;br /&gt;
			if ( this.cancelled ) { $head.last().show(); }&lt;br /&gt;
			mw.cookie.set( 'catAlotO', ns ); // Let stay open on new window&lt;br /&gt;
		} else { // Reset&lt;br /&gt;
			$dataContainer.hide();&lt;br /&gt;
			$container&lt;br /&gt;
				.draggable( 'destroy' )&lt;br /&gt;
				.resizable( 'destroy' )&lt;br /&gt;
				.removeAttr( 'style' );&lt;br /&gt;
			// Unbind click handlers&lt;br /&gt;
			this.labels.off( 'click.catALot' );&lt;br /&gt;
			this.setHeight = 450;&lt;br /&gt;
			$link.text( 'Cat-a-lot' )&lt;br /&gt;
				.nextAll().hide();&lt;br /&gt;
			this.executed = 1;&lt;br /&gt;
			mw.cookie.set( 'catAlotO', null );&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	manageSettings: function () {&lt;br /&gt;
		mw.loader.using( [ 'ext.gadget.SettingsManager', 'ext.gadget.SettingsUI', 'jquery.ui.progressbar' ], CAL._manageSettings );&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	_manageSettings: function () {&lt;br /&gt;
		mw.libs.SettingsUI( CAL.defaults, 'Cat-a-lot' )&lt;br /&gt;
			.show()&lt;br /&gt;
			.done( function ( s, verbose, loc, settingsOut, $dlg ) {&lt;br /&gt;
				var mustRestart = false,&lt;br /&gt;
					_restart = function () {&lt;br /&gt;
						if ( !mustRestart ) { return; }&lt;br /&gt;
						$container.remove();&lt;br /&gt;
						CAL.labels.off( 'click.catALot' );&lt;br /&gt;
						CAL.init();&lt;br /&gt;
					},&lt;br /&gt;
					_saveToJS = function () {&lt;br /&gt;
						var opt = mw.libs.settingsManager.option( {&lt;br /&gt;
								optionName: 'catALotPrefs',&lt;br /&gt;
								value: CAL.settings,&lt;br /&gt;
								encloseSignature: 'catALot',&lt;br /&gt;
								encloseBlock: '////////// Cat-a-lot user preferences //////////\n',&lt;br /&gt;
								triggerSaveAt: /Cat.?A.?Lot/i,&lt;br /&gt;
								editSummary: msg( 'pref-save-summary' )&lt;br /&gt;
							} ),&lt;br /&gt;
							oldHeight = $dlg.height(),&lt;br /&gt;
							$prog = $( '&amp;lt;div&amp;gt;' );&lt;br /&gt;
&lt;br /&gt;
						$dlg.css( 'height', oldHeight )&lt;br /&gt;
							.html( '' );&lt;br /&gt;
						$prog.css( {&lt;br /&gt;
							height: Math.round( oldHeight / 8 ),&lt;br /&gt;
							'margin-top': Math.round( ( 7 * oldHeight ) / 16 )&lt;br /&gt;
						} )&lt;br /&gt;
							.appendTo( $dlg );&lt;br /&gt;
&lt;br /&gt;
						$dlg.parent()&lt;br /&gt;
							.find( '.ui-dialog-buttonpane button' )&lt;br /&gt;
							.button( 'option', 'disabled', true );&lt;br /&gt;
&lt;br /&gt;
						opt.save()&lt;br /&gt;
							.done( function ( text, progress ) {&lt;br /&gt;
								$prog.progressbar( {&lt;br /&gt;
									value: progress&lt;br /&gt;
								} );&lt;br /&gt;
								$prog.fadeOut( function () {&lt;br /&gt;
									$dlg.dialog( 'close' );&lt;br /&gt;
									_restart();&lt;br /&gt;
								} );&lt;br /&gt;
							} )&lt;br /&gt;
							.progress( function ( text, progress ) {&lt;br /&gt;
								$prog.progressbar( {&lt;br /&gt;
									value: progress&lt;br /&gt;
								} );&lt;br /&gt;
							// TODO: Add &amp;quot;details&amp;quot; to progressbar&lt;br /&gt;
							} )&lt;br /&gt;
							.fail( function ( text ) {&lt;br /&gt;
								$prog.addClass( 'ui-state-error' );&lt;br /&gt;
								$dlg.prepend( $( '&amp;lt;p&amp;gt;' )&lt;br /&gt;
									.text( text ) );&lt;br /&gt;
							} );&lt;br /&gt;
					};&lt;br /&gt;
				$.each( settingsOut, function ( n, v ) {&lt;br /&gt;
					if ( v.forcerestart &amp;amp;&amp;amp; CAL.settings[ v.name ] !== v.value ) { mustRestart = true; }&lt;br /&gt;
					CAL.settings[ v.name ] = CAL.catALotPrefs[ v.name ] = v.value;&lt;br /&gt;
				} );&lt;br /&gt;
				switch ( loc ) {&lt;br /&gt;
					case 'page':&lt;br /&gt;
						$dlg.dialog( 'close' );&lt;br /&gt;
						_restart();&lt;br /&gt;
						break;&lt;br /&gt;
					case 'account-publicly':&lt;br /&gt;
						_saveToJS();&lt;br /&gt;
						break;&lt;br /&gt;
				}&lt;br /&gt;
			} );&lt;br /&gt;
	},&lt;br /&gt;
&lt;br /&gt;
	_initSettings: function () {&lt;br /&gt;
		if ( this.settings.watchlist ) { return; }&lt;br /&gt;
		this.catALotPrefs = window.catALotPrefs || {};&lt;br /&gt;
		for ( var i = 0; i &amp;lt; this.defaults.length; i++ ) {&lt;br /&gt;
			var v = this.defaults[ i ];&lt;br /&gt;
			v.value = this.settings[ v.name ] = ( this.catALotPrefs[ v.name ] || v['default'] );&lt;br /&gt;
			v.label = msg( v.label_i18n );&lt;br /&gt;
			if ( v.select_i18n ) {&lt;br /&gt;
				v.select = {};&lt;br /&gt;
				$.each( v.select_i18n, function ( i18nk, val ) {&lt;br /&gt;
					v.select[ msg( i18nk ) ] = val;&lt;br /&gt;
				} );&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	/* eslint-disable camelcase */&lt;br /&gt;
	defaults: [ {&lt;br /&gt;
		name: 'watchlist',&lt;br /&gt;
		'default': 'preferences',&lt;br /&gt;
		label_i18n: 'watchlistpref',&lt;br /&gt;
		select_i18n: {&lt;br /&gt;
			watch_pref: 'preferences',&lt;br /&gt;
			watch_nochange: 'nochange',&lt;br /&gt;
			watch_watch: 'watch',&lt;br /&gt;
			watch_unwatch: 'unwatch'&lt;br /&gt;
		}&lt;br /&gt;
	}, {&lt;br /&gt;
		name: 'minor',&lt;br /&gt;
		'default': false,&lt;br /&gt;
		label_i18n: 'minorpref'&lt;br /&gt;
	}, {&lt;br /&gt;
		name: 'editpages',&lt;br /&gt;
		'default': project !== 'commonswiki', // on Commons false&lt;br /&gt;
		label_i18n: 'editpagespref',&lt;br /&gt;
		forcerestart: true&lt;br /&gt;
	}, {&lt;br /&gt;
		name: 'docleanup',&lt;br /&gt;
		'default': false,&lt;br /&gt;
		label_i18n: 'docleanuppref'&lt;br /&gt;
	}, {&lt;br /&gt;
		name: 'subcatcount',&lt;br /&gt;
		'default': 50,&lt;br /&gt;
		min: 5,&lt;br /&gt;
		max: 500,&lt;br /&gt;
		label_i18n: 'subcatcountpref',&lt;br /&gt;
		forcerestart: true&lt;br /&gt;
	}, {&lt;br /&gt;
		name: 'uncat',&lt;br /&gt;
		'default': project === 'commonswiki', // on Commons true&lt;br /&gt;
		label_i18n: 'uncatpref'&lt;br /&gt;
	}, {&lt;br /&gt;
		name: 'button',&lt;br /&gt;
		'default': true,&lt;br /&gt;
		label_i18n: 'buttonpref'&lt;br /&gt;
	} ]&lt;br /&gt;
/* eslint-enable camelcase */&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// The gadget is not immediately needed, so let the page load normally&lt;br /&gt;
window.setTimeout( function () {&lt;br /&gt;
	non = mw.config.get( 'wgUserName' );&lt;br /&gt;
	if ( non ) {&lt;br /&gt;
		if ( mw.config.get( 'wgRelevantUserName' ) === non ) { non = 0; } else {&lt;br /&gt;
			$.each( [ 'sysop', 'filemover', 'editor', 'rollbacker', 'patroller', 'autopatrolled', 'image-reviewer', 'reviewer', 'extendedconfirmed' ], function ( i, v ) {&lt;br /&gt;
				non = $.inArray( v, userGrp ) === -1;&lt;br /&gt;
				return non;&lt;br /&gt;
			} );&lt;br /&gt;
		}&lt;br /&gt;
	} else { non = 1; }&lt;br /&gt;
&lt;br /&gt;
	switch ( ns ) {&lt;br /&gt;
		case 14:&lt;br /&gt;
			CAL.searchmode = 'category';&lt;br /&gt;
			CAL.origin = mw.config.get( 'wgTitle' );&lt;br /&gt;
			break;&lt;br /&gt;
		case -1:&lt;br /&gt;
			CAL.searchmode = {&lt;br /&gt;
			// list of accepted special page names mapped to search mode names&lt;br /&gt;
				Contributions: 'contribs',&lt;br /&gt;
				Listfiles: non ? null : 'listfiles',&lt;br /&gt;
				Prefixindex: non ? null : 'prefix',&lt;br /&gt;
				Search: 'search',&lt;br /&gt;
				Uncategorizedimages: 'gallery'&lt;br /&gt;
			}[ mw.config.get( 'wgCanonicalSpecialPageName' ) ];&lt;br /&gt;
			break;&lt;br /&gt;
		case 2:&lt;br /&gt;
		case 0:&lt;br /&gt;
			CAL.searchmode = 'gallery';&lt;br /&gt;
			var parents = $( '#mw-normal-catlinks ul' ).find( 'a[title]' ), n;&lt;br /&gt;
			parents.each( function ( i ) {&lt;br /&gt;
				if ( new RegExp( mw.config.get( 'wgTitle' ), 'i' ).test( $( this ).text() ) ) {&lt;br /&gt;
					n = i;&lt;br /&gt;
					return false;&lt;br /&gt;
				}&lt;br /&gt;
			} );&lt;br /&gt;
			CAL.origin = parents.eq( n || 0 ).text();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if ( CAL.searchmode ) {&lt;br /&gt;
		var loadingLocalizations = 1;&lt;br /&gt;
		var loadLocalization = function ( lang, cb ) {&lt;br /&gt;
			loadingLocalizations++;&lt;br /&gt;
			switch ( lang ) {&lt;br /&gt;
				case 'zh-hk':&lt;br /&gt;
				case 'zh-mo':&lt;br /&gt;
				case 'zh-tw':&lt;br /&gt;
					lang = 'zh-hant';&lt;br /&gt;
					break;&lt;br /&gt;
				case 'zh':&lt;br /&gt;
				case 'zh-cn':&lt;br /&gt;
				case 'zh-my':&lt;br /&gt;
				case 'zh-sg':&lt;br /&gt;
					lang = 'zh-hans';&lt;br /&gt;
					break;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			$.ajax( {&lt;br /&gt;
				url: commonsURL,&lt;br /&gt;
				dataType: 'script',&lt;br /&gt;
				data: {&lt;br /&gt;
					title: 'MediaWiki:Gadget-Cat-a-lot.js/' + lang,&lt;br /&gt;
					action: 'raw',&lt;br /&gt;
					ctype: 'text/javascript',&lt;br /&gt;
					// Allow caching for 28 days&lt;br /&gt;
					maxage: 2419200,&lt;br /&gt;
					smaxage: 2419200&lt;br /&gt;
				},&lt;br /&gt;
				cache: true,&lt;br /&gt;
				success: cb,&lt;br /&gt;
				error: cb&lt;br /&gt;
			} );&lt;br /&gt;
		};&lt;br /&gt;
		var maybeLaunch = function () {&lt;br /&gt;
			loadingLocalizations--;&lt;br /&gt;
			function init() {&lt;br /&gt;
				$( function () {&lt;br /&gt;
					CAL.init();&lt;br /&gt;
				} );&lt;br /&gt;
			}&lt;br /&gt;
			if ( !loadingLocalizations ) { mw.loader.using( [ 'user' ], init, init ); }&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		var userlang = mw.config.get( 'wgUserLanguage' ),&lt;br /&gt;
			contlang = mw.config.get( 'wgContentLanguage' );&lt;br /&gt;
		if ( userlang !== 'en' ) { loadLocalization( userlang, maybeLaunch ); }&lt;br /&gt;
		if ( $.inArray( contlang, [ 'en', userlang ] ) === -1 ) { loadLocalization( contlang, maybeLaunch ); }&lt;br /&gt;
		maybeLaunch();&lt;br /&gt;
	}&lt;br /&gt;
}, 400 );&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
*  Derivative work of&lt;br /&gt;
*  (replace &amp;quot;checkboxes&amp;quot; with cat-a-lot labels in your mind)&lt;br /&gt;
**&lt;br /&gt;
* jQuery checkboxShiftClick&lt;br /&gt;
*&lt;br /&gt;
* This will enable checkboxes to be checked or unchecked in a row by clicking one, holding shift and clicking another one&lt;br /&gt;
*&lt;br /&gt;
* @author Krinkle &amp;lt;krinklemail@gmail.com&amp;gt;&lt;br /&gt;
* @license GPL v2&lt;br /&gt;
*/&lt;br /&gt;
$.fn.catALotShiftClick = function ( cb ) {&lt;br /&gt;
	var prevCheckbox = null,&lt;br /&gt;
		$box = this;&lt;br /&gt;
	// When our boxes are clicked..&lt;br /&gt;
	$box.on( 'click.catALot', function ( e ) {&lt;br /&gt;
	// Prevent following the link and text selection&lt;br /&gt;
		if ( !e.ctrlKey ) { e.preventDefault(); }&lt;br /&gt;
		// Highlight last selected&lt;br /&gt;
		$( '#cat_a_lot_last_selected' )&lt;br /&gt;
			.removeAttr( 'id' );&lt;br /&gt;
		var $thisControl = $( e.target ),&lt;br /&gt;
			method;&lt;br /&gt;
		if ( !$thisControl.hasClass( 'cat_a_lot_label' ) ) { $thisControl = $thisControl.parents( '.cat_a_lot_label' ); }&lt;br /&gt;
&lt;br /&gt;
		$thisControl.attr( 'id', 'cat_a_lot_last_selected' )&lt;br /&gt;
			.toggleClass( 'cat_a_lot_selected' );&lt;br /&gt;
		// And one has been clicked before…&lt;br /&gt;
		if ( prevCheckbox !== null &amp;amp;&amp;amp; e.shiftKey ) {&lt;br /&gt;
			method = $thisControl.hasClass( 'cat_a_lot_selected' ) ? 'addClass' : 'removeClass';&lt;br /&gt;
			// Check or uncheck this one and all in-between checkboxes&lt;br /&gt;
			$box.slice(&lt;br /&gt;
				Math.min( $box.index( prevCheckbox ), $box.index( $thisControl ) ),&lt;br /&gt;
				Math.max( $box.index( prevCheckbox ), $box.index( $thisControl ) ) + 1&lt;br /&gt;
			)[ method ]( 'cat_a_lot_selected' );&lt;br /&gt;
		}&lt;br /&gt;
		// Either way, update the prevCheckbox variable to the one clicked now&lt;br /&gt;
		prevCheckbox = $thisControl;&lt;br /&gt;
		if ( $.isFunction( cb ) ) { cb(); }&lt;br /&gt;
	} );&lt;br /&gt;
	return $box;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
}( jQuery, mediaWiki ) );&lt;br /&gt;
// &amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=Pengguna:Hilmanasdf&amp;diff=105</id>
		<title>Pengguna:Hilmanasdf</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=Pengguna:Hilmanasdf&amp;diff=105"/>
		<updated>2018-07-26T04:08:04Z</updated>

		<summary type="html">&lt;p&gt;Administrator: Membuat halaman pengguna dengan biografi pengguna baru.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Anggota Aktif Indonesia Netaudio Forum.&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=Pembicaraan_Pengguna:Hilmanasdf&amp;diff=106</id>
		<title>Pembicaraan Pengguna:Hilmanasdf</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=Pembicaraan_Pengguna:Hilmanasdf&amp;diff=106"/>
		<updated>2018-07-26T04:08:04Z</updated>

		<summary type="html">&lt;p&gt;Administrator: Selamat datang!&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Welcome to ''Indonesia NetAudio Forum''!'''&lt;br /&gt;
We hope you will contribute much and well.&lt;br /&gt;
You will probably want to read the [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents help pages].&lt;br /&gt;
Again, welcome and have fun! [[Pengguna:Administrator|Administrator]] ([[Pembicaraan Pengguna:Administrator|bicara]]) 26 Juli 2018 11.08 (WIB)&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=MediaWiki:Sidebar&amp;diff=62</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=MediaWiki:Sidebar&amp;diff=62"/>
		<updated>2018-05-27T16:27:46Z</updated>

		<summary type="html">&lt;p&gt;Administrator: ←Membuat halaman berisi ' * navigation ** mainpage|mainpage-description ** recentchanges-url|recentchanges ** Category:Articles|Articles ** Category:Interviews|Interviews ** Category:Events|Ev...'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
* navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
** Category:Articles|Articles&lt;br /&gt;
** Category:Interviews|Interviews&lt;br /&gt;
** Category:Events|Events&lt;br /&gt;
** Category:Releases|Releases&lt;br /&gt;
** Category:Reviews|Reviews&lt;br /&gt;
** Category:Contributors|Contributors &lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=Halaman_Utama&amp;diff=61</id>
		<title>Halaman Utama</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=Halaman_Utama&amp;diff=61"/>
		<updated>2018-05-27T16:19:37Z</updated>

		<summary type="html">&lt;p&gt;Administrator: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;border: 1px solid #ccc; padding-left: 2%; padding-right: 2%; padding-top: 2%;padding-bottom: 2%;margin-bottom:1.75em;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h2 style=&amp;quot;padding-top:0px;margin-top:15px;&amp;quot;&amp;gt;Berita terkini&amp;lt;/h2&amp;gt;&lt;br /&gt;
{{Event summary&lt;br /&gt;
| judul = Interview with Yes No Wave Music Local Netlabel&lt;br /&gt;
| ringkasan = Awalnya sih sbenernya ga ada niatan untuk membuat sebuah label rekaman karena hanya sekedar ketertarikan saya (Wok the Rock) pada percepatan teknologi digital dan output produksinya terhadap kebebasan berpendapat dan berkarya di masyarakat luas. Konsep opensource bagi saya adalah sebuah konsep yang sangat brilian dan mulia yang dihasilkan oleh manusia di akhir abad 20 yang dikemudian hari diaplikasikan menjadi program2 populer yang benar2 memberikan kontribusi besar bagi hajat hidup orang banyak, seperti dibangunnya situs Wikipedia, browser Firefox, perpustakaan digital The Internet Archive hingga model hak cipta karya digital di Creative Commons, dsb yang kesemuanya itu memiliki sifat yang sama, yaitu gratis, bebas dimodifikasi, adanya kemungkinan besar untuk saling berkolaborasi dan didedikasikan bagi perkembangan ilmu pengetahuan yang open-mind bagi masyarakat dunia. Kaum marxis dan seniman Dadaism kuno wajib hormat dengan teknologi ini.&lt;br /&gt;
| foto = &lt;br /&gt;
}}&lt;br /&gt;
{{Event summary&lt;br /&gt;
| judul = MP3: The Meaning of a Format – Jonathan Sterne&lt;br /&gt;
| ringkasan = “Although it is a ubiquitous and banal technology, the MP3 offers an inviting point of entry into interconnected histories of sound and communication in the twentieth century.”&lt;br /&gt;
&lt;br /&gt;
Sejak tahun 90an, MP3 adalah format audio yang paling populer beredar untuk rekaman audio. MP3 telah menjadi keseharian warga dunia, bergerak dengan lincah di Internet hingga perekonomian jalanan. Lebih banyak album rekaman yang tersirkulasikan dalam format MP3 ketimbang dalam format lainnya. Rekaman yang memasuki dunia Internet akan berjelajah dalam format MP3. Dalam “MP3: The Meaning of a Format”, Jonathan Sterne dengan baik mengulas perkembangan teknologi MP3 dan fenomena sosial yang terjadi di sekitarnya.&lt;br /&gt;
| foto = &lt;br /&gt;
}}&lt;br /&gt;
{{Event summary&lt;br /&gt;
| judul = Lapis “Kasta” Bernama MP3: Sebuah Amatan Atas Kedalaman Musik&lt;br /&gt;
| ringkasan = Kita boleh setuju atau tidak, bahwa di dalam musik, atau lintas keseharian kita, ada drajat tentang telinga dan fungsinya. Sedikitnya tiga: Mendengar (hearing), mendengarkan (listening), dan mendengarkan secara mendalam (deep listening). Mana yang wajib dan mana yang sunnah? Kualitas peradaban mungkin bisa mulai disisir dari telinga dan fungsinya tersebut, bukan hanya dari koar-koar politis yang menggaung menghabiskan banyak duit rakyat tapi sebenarnya bisu.&lt;br /&gt;
| foto = &lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=Templat:Event_summary&amp;diff=60</id>
		<title>Templat:Event summary</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=Templat:Event_summary&amp;diff=60"/>
		<updated>2018-05-27T16:16:16Z</updated>

		<summary type="html">&lt;p&gt;Administrator: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable plainlinks&amp;quot; style=&amp;quot;margin: auto; width: 100%; border: 1px grey solid; border-top: 9px blue solid;&amp;quot;&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: center;&amp;quot; | {{#if:{{{judul&amp;lt;noinclude&amp;gt;|&amp;lt;/noinclude&amp;gt;}}}|[[{{{judul}}}]]|&amp;amp;ndash;}}&lt;br /&gt;
|-&lt;br /&gt;
| width=75% | {{#if:{{{foto|}}}|[[Berkas:{{{foto}}}|120px|frameless|right]]|&amp;amp;nbsp;}}&lt;br /&gt;
{{#if:{{{ringkasan&amp;lt;noinclude&amp;gt;|&amp;lt;/noinclude&amp;gt;}}}|{{{ringkasan}}}&amp;amp;nbsp;''[[{{{judul}}}|Selengkapnya…]]''|&amp;amp;nbsp;}}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=Templat:Event_summary&amp;diff=59</id>
		<title>Templat:Event summary</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=Templat:Event_summary&amp;diff=59"/>
		<updated>2018-05-27T16:15:33Z</updated>

		<summary type="html">&lt;p&gt;Administrator: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable plainlinks&amp;quot; style=&amp;quot;margin: auto; width: 100%; border: 1px grey solid; border-top: 9px blue solid;&amp;quot;&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: center;&amp;quot; | {{#if:{{{judul&amp;lt;noinclude&amp;gt;|&amp;lt;/noinclude&amp;gt;}}}|[[{{{judul}}}]]|&amp;amp;ndash;}}&lt;br /&gt;
|-&lt;br /&gt;
| width=75% | {{#if:{{{foto|}}}|[[Berkas:{{{foto}}}|120px|frameless|right]]|&amp;lt;center&amp;gt;&amp;amp;nbsp;&amp;lt;/center&amp;gt;}}&lt;br /&gt;
{{#if:{{{ringkasan&amp;lt;noinclude&amp;gt;|&amp;lt;/noinclude&amp;gt;}}}|{{{ringkasan}}}&amp;amp;nbsp;''[[{{{judul}}}|Selengkapnya…]]''|&amp;amp;nbsp;}}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=Templat:Event_summary&amp;diff=58</id>
		<title>Templat:Event summary</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=Templat:Event_summary&amp;diff=58"/>
		<updated>2018-05-27T16:13:24Z</updated>

		<summary type="html">&lt;p&gt;Administrator: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable plainlinks&amp;quot; style=&amp;quot;margin: auto; width: 100%; border: 1px grey solid; border-top: 9px blue solid;&amp;quot;&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: center;&amp;quot; | {{#if:{{{judul&amp;lt;noinclude&amp;gt;|&amp;lt;/noinclude&amp;gt;}}}|{{{judul}}}|&amp;amp;ndash;}}&lt;br /&gt;
|-&lt;br /&gt;
| width=75% | {{#if:{{{foto|}}}|[[Berkas:{{{foto}}}|120px|frameless|right]]|&amp;lt;center&amp;gt;&amp;amp;nbsp;&amp;lt;/center&amp;gt;}}&lt;br /&gt;
{{#if:{{{ringkasan&amp;lt;noinclude&amp;gt;|&amp;lt;/noinclude&amp;gt;}}}|{{{ringkasan}}}&amp;amp;nbsp;''[[{{{judul}}}|Selengkapnya…]]''|&amp;amp;nbsp;}}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=Templat:Event_summary&amp;diff=57</id>
		<title>Templat:Event summary</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=Templat:Event_summary&amp;diff=57"/>
		<updated>2018-05-27T16:11:34Z</updated>

		<summary type="html">&lt;p&gt;Administrator: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable plainlinks&amp;quot; style=&amp;quot;margin: auto; width: 100%; border: 1px grey solid; border-top: 9px blue solid;&amp;quot;&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: center;&amp;quot; | {{#if:{{{judul&amp;lt;noinclude&amp;gt;|&amp;lt;/noinclude&amp;gt;}}}|{{{judul}}}|&amp;amp;ndash;}}&lt;br /&gt;
|-&lt;br /&gt;
| width=75% | {{#if:{{{foto|}}}|[[Berkas:{{{foto}}}|120px|frameless|right]]|&amp;lt;center&amp;gt;&amp;amp;nbsp;&amp;lt;/center&amp;gt;}}&lt;br /&gt;
{{#if:{{{ringkasan&amp;lt;noinclude&amp;gt;|&amp;lt;/noinclude&amp;gt;}}}|{{{ringkasan}}}|&amp;amp;nbsp;}}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=Halaman_Utama&amp;diff=56</id>
		<title>Halaman Utama</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=Halaman_Utama&amp;diff=56"/>
		<updated>2018-05-27T16:10:36Z</updated>

		<summary type="html">&lt;p&gt;Administrator: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;border: 1px solid #ccc; padding-left: 2%; padding-right: 2%; padding-top: 2%;padding-bottom: 2%;margin-bottom:1.75em;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h2 style=&amp;quot;padding-top:0px;margin-top:15px;&amp;quot;&amp;gt;Kegiatan kami&amp;lt;/h2&amp;gt;&lt;br /&gt;
{{Event summary&lt;br /&gt;
| judul = [[Interview with Yes No Wave Music Local Netlabel]]&lt;br /&gt;
| ringkasan = Awalnya sih sbenernya ga ada niatan untuk membuat sebuah label rekaman karena hanya sekedar ketertarikan saya (Wok the Rock) pada percepatan teknologi digital dan output produksinya terhadap kebebasan berpendapat dan berkarya di masyarakat luas. Konsep opensource bagi saya adalah sebuah konsep yang sangat brilian dan mulia yang dihasilkan oleh manusia di akhir abad 20 yang dikemudian hari diaplikasikan menjadi program2 populer yang benar2 memberikan kontribusi besar bagi hajat hidup orang banyak, seperti dibangunnya situs Wikipedia, browser Firefox, perpustakaan digital The Internet Archive hingga model hak cipta karya digital di Creative Commons, dsb yang kesemuanya itu memiliki sifat yang sama, yaitu gratis, bebas dimodifikasi, adanya kemungkinan besar untuk saling berkolaborasi dan didedikasikan bagi perkembangan ilmu pengetahuan yang open-mind bagi masyarakat dunia. Kaum marxis dan seniman Dadaism kuno wajib hormat dengan teknologi ini.&lt;br /&gt;
| foto = &lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=Halaman_Utama&amp;diff=11</id>
		<title>Halaman Utama</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=Halaman_Utama&amp;diff=11"/>
		<updated>2018-03-28T15:55:38Z</updated>

		<summary type="html">&lt;p&gt;Administrator: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;border: 1px solid #ccc; padding-left: 2%; padding-right: 2%; padding-top: 2%;padding-bottom: 2%;margin-bottom:1.75em;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h2 style=&amp;quot;padding-top:0px;margin-top:15px;&amp;quot;&amp;gt;Kegiatan kami&amp;lt;/h2&amp;gt;&lt;br /&gt;
{{Event summary&lt;br /&gt;
| judul = [[Lorem ipsum]]&lt;br /&gt;
| ringkasan = Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.&lt;br /&gt;
&lt;br /&gt;
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. &lt;br /&gt;
&lt;br /&gt;
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.&lt;br /&gt;
| foto = Wikipedia-logo-v2.svg&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=Halaman_Utama&amp;diff=10</id>
		<title>Halaman Utama</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=Halaman_Utama&amp;diff=10"/>
		<updated>2018-03-28T15:54:39Z</updated>

		<summary type="html">&lt;p&gt;Administrator: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;border: 1px solid #ccc; padding-left: 2%; padding-right: 2%; padding-top: 2%;padding-bottom: 2%;margin-bottom:1.75em;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h2 style=&amp;quot;padding-top:0px;margin-top:15px;&amp;quot;&amp;gt;Kegiatan&amp;lt;/h2&amp;gt;&lt;br /&gt;
{{Event summary&lt;br /&gt;
| judul = Lorem ipsum&lt;br /&gt;
| ringkasan = Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.&lt;br /&gt;
&lt;br /&gt;
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. &lt;br /&gt;
&lt;br /&gt;
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.&lt;br /&gt;
| foto = Wikipedia-logo-v2.svg&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=Templat:Event_summary&amp;diff=9</id>
		<title>Templat:Event summary</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=Templat:Event_summary&amp;diff=9"/>
		<updated>2018-03-28T15:53:12Z</updated>

		<summary type="html">&lt;p&gt;Administrator: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable plainlinks&amp;quot; style=&amp;quot;margin: auto; width: 100%; border: 1px grey solid; border-top: 9px blue solid;&amp;quot;&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: center;&amp;quot; | {{#if:{{{judul&amp;lt;noinclude&amp;gt;|&amp;lt;/noinclude&amp;gt;}}}|{{{judul}}}|&amp;amp;ndash;}}&lt;br /&gt;
|-&lt;br /&gt;
| width=75% | {{#if:{{{foto|}}}|[[Berkas:{{{foto}}}|120px|frameless|right]]|&amp;lt;center&amp;gt;&amp;amp;ndash;&amp;lt;/center&amp;gt;}}&lt;br /&gt;
{{#if:{{{ringkasan&amp;lt;noinclude&amp;gt;|&amp;lt;/noinclude&amp;gt;}}}|{{{ringkasan}}}|&amp;amp;ndash;}}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=Templat:Event_summary&amp;diff=8</id>
		<title>Templat:Event summary</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=Templat:Event_summary&amp;diff=8"/>
		<updated>2018-03-28T15:52:54Z</updated>

		<summary type="html">&lt;p&gt;Administrator: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable plainlinks&amp;quot; style=&amp;quot;margin: auto; width: 100%; border: 1px grey solid; border-top: 9px blue solid;&amp;quot;&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: center;&amp;quot; | {{#if:{{{judul&amp;lt;noinclude&amp;gt;|&amp;lt;/noinclude&amp;gt;}}}|{{{judul}}}|&amp;amp;ndash;}}&lt;br /&gt;
|-&lt;br /&gt;
| width=75% | {{#if:{{{foto|}}}|[[Berkas:{{{foto}}}|120px|frameless|center]]|&amp;lt;center&amp;gt;&amp;amp;ndash;&amp;lt;/center&amp;gt;}}&lt;br /&gt;
{{#if:{{{ringkasan&amp;lt;noinclude&amp;gt;|&amp;lt;/noinclude&amp;gt;}}}|{{{ringkasan}}}|&amp;amp;ndash;}}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=Templat:Event_summary&amp;diff=7</id>
		<title>Templat:Event summary</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=Templat:Event_summary&amp;diff=7"/>
		<updated>2018-03-28T15:52:19Z</updated>

		<summary type="html">&lt;p&gt;Administrator: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable plainlinks&amp;quot; style=&amp;quot;margin: auto; width: 100%; border: 1px grey solid; border-top: 9px blue solid;&amp;quot;&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: center;&amp;quot; | {{#if:{{{judul&amp;lt;noinclude&amp;gt;|&amp;lt;/noinclude&amp;gt;}}}|{{{judul}}}|&amp;amp;ndash;}}&lt;br /&gt;
|-&lt;br /&gt;
| width=75% | {{#if:{{{ringkasan&amp;lt;noinclude&amp;gt;|&amp;lt;/noinclude&amp;gt;}}}|{{{ringkasan}}}|&amp;amp;ndash;}}&lt;br /&gt;
| {{#if:{{{foto|}}}|[[Berkas:{{{foto}}}|120px|frameless|center]]|&amp;lt;center&amp;gt;&amp;amp;ndash;&amp;lt;/center&amp;gt;}}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=Templat:Event_summary&amp;diff=6</id>
		<title>Templat:Event summary</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=Templat:Event_summary&amp;diff=6"/>
		<updated>2018-03-28T15:51:39Z</updated>

		<summary type="html">&lt;p&gt;Administrator: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable plainlinks&amp;quot; style=&amp;quot;margin: auto; width: 100%; border: 1px grey solid; border-top: 9px blue solid;&amp;quot;&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: center;&amp;quot; | {{#if:{{{judul&amp;lt;noinclude&amp;gt;|&amp;lt;/noinclude&amp;gt;}}}|{{{judul}}}|&amp;amp;ndash;}}&lt;br /&gt;
|-&lt;br /&gt;
| width=75% | {{#if:{{{ringkasan&amp;lt;noinclude&amp;gt;|&amp;lt;/noinclude&amp;gt;}}}|{{{ringkasan}}}|&amp;amp;ndash;}}&lt;br /&gt;
| {{#if:{{{foto|}}}|[[Berkas:{{{foto}}}|220px|frameless|center]]|&amp;lt;center&amp;gt;&amp;amp;ndash;&amp;lt;/center&amp;gt;}}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=Templat:Event_summary&amp;diff=5</id>
		<title>Templat:Event summary</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=Templat:Event_summary&amp;diff=5"/>
		<updated>2018-03-28T15:50:27Z</updated>

		<summary type="html">&lt;p&gt;Administrator: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable plainlinks&amp;quot; style=&amp;quot;margin: auto; width: 100%; border: 1px grey solid; border-top: 9px blue solid;&amp;quot;&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: center;&amp;quot; | {{#if:{{{judul&amp;lt;noinclude&amp;gt;|&amp;lt;/noinclude&amp;gt;}}}|{{{judul}}}|&amp;amp;ndash;}}&lt;br /&gt;
|-&lt;br /&gt;
| width=75% | {{#if:{{{ringkasan&amp;lt;noinclude&amp;gt;|&amp;lt;/noinclude&amp;gt;}}}|{{{ringkasan}}}|&amp;amp;ndash;}}&lt;br /&gt;
| {{#if:{{{foto|}}}|[[Berkas:{{{foto}}}|260px|frameless|center]]|&amp;lt;center&amp;gt;&amp;amp;ndash;&amp;lt;/center&amp;gt;}}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=Templat:Event_summary&amp;diff=4</id>
		<title>Templat:Event summary</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=Templat:Event_summary&amp;diff=4"/>
		<updated>2018-03-28T15:47:55Z</updated>

		<summary type="html">&lt;p&gt;Administrator: ←Membuat halaman berisi '&amp;lt;includeonly&amp;gt; {| class=&amp;quot;wikitable plainlinks&amp;quot; style=&amp;quot;margin: auto; width: 100%; border: 1px grey solid; border-top: 9px blue solid;&amp;quot; ! colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: c...'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable plainlinks&amp;quot; style=&amp;quot;margin: auto; width: 100%; border: 1px grey solid; border-top: 9px blue solid;&amp;quot;&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: center;&amp;quot; | {{#if:{{{judul&amp;lt;noinclude&amp;gt;|&amp;lt;/noinclude&amp;gt;}}}|{{{judul}}}|&amp;amp;ndash;}}&lt;br /&gt;
|-&lt;br /&gt;
| {{#if:{{{ringkasan&amp;lt;noinclude&amp;gt;|&amp;lt;/noinclude&amp;gt;}}}|{{{ringkasan}}}|&amp;amp;ndash;}}&lt;br /&gt;
| {{#if:{{{foto|}}}|[[Berkas:{{{foto}}}|260px|frameless|center]]|&amp;lt;center&amp;gt;&amp;amp;ndash;&amp;lt;/center&amp;gt;}}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
	<entry>
		<id>http://indonesianetaudioforum.net/wiki/index.php?title=Halaman_Utama&amp;diff=2</id>
		<title>Halaman Utama</title>
		<link rel="alternate" type="text/html" href="http://indonesianetaudioforum.net/wiki/index.php?title=Halaman_Utama&amp;diff=2"/>
		<updated>2018-03-18T17:04:27Z</updated>

		<summary type="html">&lt;p&gt;Administrator: Administrator memindahkan halaman Main Page ke Halaman Utama tanpa membuat pengalihan&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;strong&amp;gt;MediaWiki has been installed.&amp;lt;/strong&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Consult the [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents User's Guide] for information on using the wiki software.&lt;br /&gt;
&lt;br /&gt;
== Getting started ==&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Configuration settings list]&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki FAQ]&lt;br /&gt;
* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list]&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Localise MediaWiki for your language]&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Learn how to combat spam on your wiki]&lt;/div&gt;</summary>
		<author><name>Administrator</name></author>
		
	</entry>
</feed>