<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fa">
	<id>https://fa.farahowzeh.ir/w/index.php?action=history&amp;feed=atom&amp;title=%D9%85%D8%AF%DB%8C%D8%A7%D9%88%DB%8C%DA%A9%DB%8C%3AGadget-SettingsManager.js</id>
	<title>مدیاویکی:Gadget-SettingsManager.js - تاریخچهٔ نسخه‌ها</title>
	<link rel="self" type="application/atom+xml" href="https://fa.farahowzeh.ir/w/index.php?action=history&amp;feed=atom&amp;title=%D9%85%D8%AF%DB%8C%D8%A7%D9%88%DB%8C%DA%A9%DB%8C%3AGadget-SettingsManager.js"/>
	<link rel="alternate" type="text/html" href="https://fa.farahowzeh.ir/w/index.php?title=%D9%85%D8%AF%DB%8C%D8%A7%D9%88%DB%8C%DA%A9%DB%8C:Gadget-SettingsManager.js&amp;action=history"/>
	<updated>2026-06-26T17:07:10Z</updated>
	<subtitle>تاریخچهٔ نسخه‌ها برای این صفحه در ویکی</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://fa.farahowzeh.ir/w/index.php?title=%D9%85%D8%AF%DB%8C%D8%A7%D9%88%DB%8C%DA%A9%DB%8C:Gadget-SettingsManager.js&amp;diff=362&amp;oldid=prev</id>
		<title>Esfandiari: ۲ نسخه واردشده</title>
		<link rel="alternate" type="text/html" href="https://fa.farahowzeh.ir/w/index.php?title=%D9%85%D8%AF%DB%8C%D8%A7%D9%88%DB%8C%DA%A9%DB%8C:Gadget-SettingsManager.js&amp;diff=362&amp;oldid=prev"/>
		<updated>2026-06-25T08:39:33Z</updated>

		<summary type="html">&lt;p&gt;۲ نسخه واردشده&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;fa&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;→ نسخهٔ قدیمی‌تر&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;نسخهٔ ‏۲۵ ژوئن ۲۰۲۶، ساعت ۰۸:۳۹&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;4&quot; class=&quot;diff-notice&quot; lang=&quot;fa&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(بدون تفاوت)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;!-- diff cache key farahowzeh_wifaesfand78:diff:1.41:old-361:rev-362 --&gt;
&lt;/table&gt;</summary>
		<author><name>Esfandiari</name></author>
	</entry>
	<entry>
		<id>https://fa.farahowzeh.ir/w/index.php?title=%D9%85%D8%AF%DB%8C%D8%A7%D9%88%DB%8C%DA%A9%DB%8C:Gadget-SettingsManager.js&amp;diff=361&amp;oldid=prev</id>
		<title>esfandiari&gt;Esfandiari: ۱ نسخه واردشده</title>
		<link rel="alternate" type="text/html" href="https://fa.farahowzeh.ir/w/index.php?title=%D9%85%D8%AF%DB%8C%D8%A7%D9%88%DB%8C%DA%A9%DB%8C:Gadget-SettingsManager.js&amp;diff=361&amp;oldid=prev"/>
		<updated>2026-06-19T20:52:48Z</updated>

		<summary type="html">&lt;p&gt;۱ نسخه واردشده&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;fa&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;→ نسخهٔ قدیمی‌تر&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;نسخهٔ ‏۱۹ ژوئن ۲۰۲۶، ساعت ۲۰:۵۲&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;4&quot; class=&quot;diff-notice&quot; lang=&quot;fa&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(بدون تفاوت)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;!-- diff cache key farahowzeh_wifaesfand78:diff:1.41:old-360:rev-361 --&gt;
&lt;/table&gt;</summary>
		<author><name>esfandiari&gt;Esfandiari</name></author>
	</entry>
	<entry>
		<id>https://fa.farahowzeh.ir/w/index.php?title=%D9%85%D8%AF%DB%8C%D8%A7%D9%88%DB%8C%DA%A9%DB%8C:Gadget-SettingsManager.js&amp;diff=360&amp;oldid=prev</id>
		<title>admin&gt;Nazarzadeh: صفحه‌ای تازه حاوی «/**  * :commons:MediaWiki:Gadget-SettingsManager.js  * Managing user preferences of scripts  * Managing gadgets and gadget preferences...» ایجاد کرد</title>
		<link rel="alternate" type="text/html" href="https://fa.farahowzeh.ir/w/index.php?title=%D9%85%D8%AF%DB%8C%D8%A7%D9%88%DB%8C%DA%A9%DB%8C:Gadget-SettingsManager.js&amp;diff=360&amp;oldid=prev"/>
		<updated>2020-09-20T09:04:59Z</updated>

		<summary type="html">&lt;p&gt;صفحه‌ای تازه حاوی «/**  * &lt;a href=&quot;https://commons.wikimedia.org/wiki/MediaWiki:Gadget-SettingsManager.js&quot; class=&quot;extiw&quot; title=&quot;commons:MediaWiki:Gadget-SettingsManager.js&quot;&gt;commons:MediaWiki:Gadget-SettingsManager.js&lt;/a&gt;  * Managing user preferences of scripts  * Managing gadgets and gadget preferences...» ایجاد کرد&lt;/p&gt;
&lt;p&gt;&lt;b&gt;صفحهٔ تازه&lt;/b&gt;&lt;/p&gt;&lt;div&gt;/**&lt;br /&gt;
 * [[:commons:MediaWiki:Gadget-SettingsManager.js]]&lt;br /&gt;
 * Managing user preferences of scripts&lt;br /&gt;
 * Managing gadgets and gadget preferences&lt;br /&gt;
 *&lt;br /&gt;
 * Use it for good, not for evil.&lt;br /&gt;
 *&lt;br /&gt;
 * @author Rillke, 2012&lt;br /&gt;
 * @license GPL v.3&lt;br /&gt;
 * &amp;lt;nowiki&amp;gt;&lt;br /&gt;
 */&lt;br /&gt;
 &lt;br /&gt;
// List the global variables for jsHint-Validation.&lt;br /&gt;
// Scheme: globalVariable:allowOverwriting[, globalVariable:allowOverwriting][, globalVariable:allowOverwriting]&lt;br /&gt;
/*global jQuery:false, mediaWiki:false*/&lt;br /&gt;
&lt;br /&gt;
// Set jsHint-options.&lt;br /&gt;
/*jshint forin:true, noarg:true, noempty:true, eqeqeq:true, bitwise:true, strict:true, undef:true, curly:false, browser:true*/&lt;br /&gt;
&lt;br /&gt;
( function ( $, mw ) {&lt;br /&gt;
&amp;quot;use strict&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// Different tokes exist only to confuse the user (at least in 2012)&lt;br /&gt;
// All of them carry the same value except the watchlist token&lt;br /&gt;
if (!mw.user.tokens.exists(&amp;#039;preferencesToken&amp;#039;)) mw.user.tokens.set(&amp;#039;preferencesToken&amp;#039;, mw.user.tokens.get(&amp;#039;editToken&amp;#039;));&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* Refresh preferences-token&lt;br /&gt;
*&lt;br /&gt;
* @example&lt;br /&gt;
*      refreshToken( function() { doGoodStuff.retry(); } );&lt;br /&gt;
*&lt;br /&gt;
* @param cb {Function} Callback function. The first argument supplied is whether the operation succeeded.&lt;br /&gt;
* @context {closure} private function&lt;br /&gt;
* @return {Object} a jQuery deferred-object-queue&lt;br /&gt;
*/&lt;br /&gt;
var refreshToken = function(cb) {&lt;br /&gt;
	var mwa = new mw.Api(),&lt;br /&gt;
		apiDef = mwa.get( {&lt;br /&gt;
			meta: &amp;#039;userinfo&amp;#039;,&lt;br /&gt;
			uiprop: &amp;#039;preferencestoken&amp;#039;&lt;br /&gt;
		} );&lt;br /&gt;
		&lt;br /&gt;
	apiDef.done(function(result) {&lt;br /&gt;
		if (!result.query || !result.query.userinfo) return cb( false, &amp;#039;wrong-response&amp;#039; );&lt;br /&gt;
		mw.user.tokens.set( &amp;#039;preferencesToken&amp;#039;, result.query.userinfo.preferencestoken );&lt;br /&gt;
		cb( true );&lt;br /&gt;
	});&lt;br /&gt;
	apiDef.fail(function(code, result) {&lt;br /&gt;
		if (!result.query || !result.query.userinfo) return cb( false, code );&lt;br /&gt;
	});&lt;br /&gt;
	return apiDef;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
var firstItem = function(o) { &lt;br /&gt;
	for (var i in o) {&lt;br /&gt;
		if (o.hasOwnProperty( i )) { &lt;br /&gt;
			return o[i]; &lt;br /&gt;
		} &lt;br /&gt;
	} &lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
var valByString = function(identifier) {&lt;br /&gt;
	var arr = identifier.split( &amp;#039;.&amp;#039; ),&lt;br /&gt;
		lenArr = arr.length,&lt;br /&gt;
		i,&lt;br /&gt;
		elemArr,&lt;br /&gt;
		objCurrent = window;&lt;br /&gt;
		&lt;br /&gt;
	for (i = 0; i &amp;lt; lenArr; i++) {&lt;br /&gt;
		elemArr = arr[i];&lt;br /&gt;
		objCurrent = objCurrent[elemArr];&lt;br /&gt;
	}&lt;br /&gt;
	return objCurrent;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
var mwPrefPrefix = &amp;#039;userjs-sm-&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
var sm = {&lt;br /&gt;
	version: &amp;#039;0.1.0.1&amp;#039;,&lt;br /&gt;
	errorPrefix: &amp;quot;SettingsWizard encountered a problem. We regret the inconvenience. &amp;quot;,&lt;br /&gt;
	/**&lt;br /&gt;
	* Constructor-method. Returns an option-object you should perform the actions on.&lt;br /&gt;
	*&lt;br /&gt;
	* @example&lt;br /&gt;
	*      var opt = mw.libs.settingsManager.option( { optionName: &amp;#039;CatALotOptions&amp;#039;, value: { watchCopy: false, watchRemove: false } } );&lt;br /&gt;
	*      // Save the options we&amp;#039;ve set before and make the script triggering events on the document, you can listen to&lt;br /&gt;
	*      opt.save( $(document), &amp;#039;CatALotSaveProgress&amp;#039; );&lt;br /&gt;
	*      // or, use the deferred-object returned:&lt;br /&gt;
	*      opt.save().done(function(msg, status, jsFile) { &lt;br /&gt;
	*          alert( msg );&lt;br /&gt;
	*      }).status(function(msg, status, jsFile) { &lt;br /&gt;
	*          console.log( &amp;#039;settings progress&amp;gt;&amp;#039; + msg );&lt;br /&gt;
	*      });&lt;br /&gt;
	*&lt;br /&gt;
	* @param specsIn {Object} specifications passed in. List of defaults (cf. specs) follows.&lt;br /&gt;
	* @context {mw.libs.settingsManager}&lt;br /&gt;
	* @return {Object} option-object you can use for performing actions on.&lt;br /&gt;
	*/&lt;br /&gt;
	option: function(specsIn) {&lt;br /&gt;
		// List of defaults:&lt;br /&gt;
		var specs = {&lt;br /&gt;
			// The global name the option will be saved under&lt;br /&gt;
			// This can be also something like &amp;quot;mw.settingsOfToolX&amp;quot;&lt;br /&gt;
			optionName: &amp;#039;&amp;#039;,&lt;br /&gt;
			// The position where to save them. By default options are&lt;br /&gt;
			// saved at the user&amp;#039;s common.js or &amp;lt;skin&amp;gt;.js (e.g. vector.js)&lt;br /&gt;
			// specify other locations like &amp;quot;settingsOfToolX&amp;quot; --&amp;gt; &amp;quot;User:Example/prefs/settingsOfToolX.js&amp;quot;&lt;br /&gt;
			saveAt: false,&lt;br /&gt;
			// By default the option is not enclosed in a comment-block&lt;br /&gt;
			// Comment-blocks are recommended for larger configurations&lt;br /&gt;
			// specifies the signature that will be used for the enclosing comments&lt;br /&gt;
			// blockSettingsOfToolX --&amp;gt; //blockSettingsOfToolX///////////////////////&lt;br /&gt;
			// (ignored when saveAt is set)&lt;br /&gt;
			encloseSignature: false,&lt;br /&gt;
			// Specify additional block comments added below the signature&lt;br /&gt;
			// Should be something that explains what the following JSON does or is good for&lt;br /&gt;
			// Recommended line-length for consistent alignment: 48 chars&lt;br /&gt;
			encloseBlock: false,&lt;br /&gt;
			// If no own location for saving the option is used (options that must be&lt;br /&gt;
			// available while loading the script should not be saved to a separate file while &lt;br /&gt;
			// complex options should), if the RegExp will have a match on either the common.js&lt;br /&gt;
			// or the &amp;lt;skin&amp;gt;.js, and this option is not saved yet to another .js, the option&lt;br /&gt;
			// will be saved to this js-file. In case the option is not saved yet and there is&lt;br /&gt;
			// no RegExp supplied or it did not match, the option will be saved to the larger&lt;br /&gt;
			// JavaScript&lt;br /&gt;
			triggerSaveAt: false,&lt;br /&gt;
			// Should the new content be insered in front of the match by triggerSaveAt&lt;br /&gt;
			// If none of the following options is specified, the new content &lt;br /&gt;
			// will be appended to the script&lt;br /&gt;
			insertBeforeTrigger: false,&lt;br /&gt;
			insertAfterTrigger: false,&lt;br /&gt;
			replaceTrigger: false,&lt;br /&gt;
			// Finally the option&amp;#039;s value. Objects are possible. They will be automatically&lt;br /&gt;
			// transformed into a JSON-string&lt;br /&gt;
			value: undefined,&lt;br /&gt;
			// Edit summary to use while saving the JavaScript&lt;br /&gt;
			editSummary: &amp;quot;&amp;quot;&lt;br /&gt;
		};&lt;br /&gt;
		if (!specsIn) throw new Error(sm.errorPrefix + &amp;quot;Data to save or retrieve was not supplied by the script using SettingsWizard.&amp;quot;);&lt;br /&gt;
		if (!specsIn.optionName &amp;amp;&amp;amp; !specsIn.saveAt) throw new Error(sm.errorPrefix + &amp;quot;The options\&amp;#039;s name was not supplied by the script using SettingsWizard.&amp;quot;);&lt;br /&gt;
		$.extend( true, specs, specsIn );&lt;br /&gt;
		&lt;br /&gt;
		// Prepare variables we need later&lt;br /&gt;
		var nsUser   = mw.config.get(&amp;#039;wgFormattedNamespaces&amp;#039;)[2],&lt;br /&gt;
			skin     = mw.config.get(&amp;#039;skin&amp;#039;),&lt;br /&gt;
			user     = mw.config.get(&amp;#039;wgUserName&amp;#039;),&lt;br /&gt;
			skinJS   = [nsUser, &amp;#039;:&amp;#039;, user, &amp;#039;/&amp;#039;, skin, &amp;#039;.js&amp;#039;].join(&amp;#039;&amp;#039;),&lt;br /&gt;
			commonJS = [nsUser, &amp;#039;:&amp;#039;, user, &amp;#039;/&amp;#039;,&amp;#039;common&amp;#039;, &amp;#039;.js&amp;#039;].join(&amp;#039;&amp;#039;);&lt;br /&gt;
		&lt;br /&gt;
		// Event-handler system&lt;br /&gt;
		var $el, evt, jsFiles, process, $progress = new $.Deferred(), customJS;&lt;br /&gt;
		var triggerEvt = function(any) {&lt;br /&gt;
			return (evt &amp;amp;&amp;amp; $el &amp;amp;&amp;amp; $el instanceof jQuery &amp;amp;&amp;amp; $el.triggerHandler( evt, Array.prototype.slice.call( arguments, 0 ) ));&lt;br /&gt;
		};&lt;br /&gt;
		&lt;br /&gt;
		process = {&lt;br /&gt;
			updateVars: function() {&lt;br /&gt;
				// Reset variables that could be polluted&lt;br /&gt;
				jsFiles = [];&lt;br /&gt;
				$progress = new $.Deferred();&lt;br /&gt;
				customJS = [nsUser, &amp;#039;:&amp;#039;, user, &amp;#039;/prefs/&amp;#039;, specs.saveAt, &amp;#039;.js&amp;#039;].join(&amp;#039;&amp;#039;);&lt;br /&gt;
			},&lt;br /&gt;
			start: function() {&lt;br /&gt;
				this.updateVars();&lt;br /&gt;
				&lt;br /&gt;
				// Subscribe to any event: We want to know everything :-)&lt;br /&gt;
				$progress.then( triggerEvt, triggerEvt, triggerEvt );&lt;br /&gt;
				&lt;br /&gt;
				// Always async&lt;br /&gt;
				setTimeout( $.proxy( this.getScripts, this ), 1 );&lt;br /&gt;
				&lt;br /&gt;
				return $progress;&lt;br /&gt;
			},&lt;br /&gt;
			getScripts: function() {&lt;br /&gt;
				var i, len;&lt;br /&gt;
				&lt;br /&gt;
				$progress.notify( &amp;quot;Preparing&amp;quot;, 1 );&lt;br /&gt;
				&lt;br /&gt;
				// First, we need something to work on/ edit token, etc. - request the JavaScript(s)&lt;br /&gt;
				if (specs.saveAt) {&lt;br /&gt;
					jsFiles.push( sm.script( customJS ) );&lt;br /&gt;
				} else {&lt;br /&gt;
					jsFiles.push( sm.script( skinJS ) );&lt;br /&gt;
					jsFiles.push( sm.script( commonJS ) );&lt;br /&gt;
				}&lt;br /&gt;
				len = jsFiles.length;&lt;br /&gt;
				for (i = 0; i &amp;lt; len; i++) {&lt;br /&gt;
					var jsFile = jsFiles[i];&lt;br /&gt;
					jsFile.fetchText( process.gotJS, process.gotJSErr );&lt;br /&gt;
					$progress.notify( &amp;quot;Requesting &amp;quot; + jsFile.getSource(), Math.round( (i+1)*(9/len) ) + 1, jsFile );&lt;br /&gt;
				}&lt;br /&gt;
				return $progress;&lt;br /&gt;
			},&lt;br /&gt;
			gotJS: function(jsFile, r){&lt;br /&gt;
				jsFile.gotContent = true;&lt;br /&gt;
				&lt;br /&gt;
				var i, len = jsFiles.length, pendings = 0;&lt;br /&gt;
				for (i = 0; i &amp;lt; len; i++) {&lt;br /&gt;
					if (!jsFiles[i].gotContent) {&lt;br /&gt;
						pendings++;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				$progress.notify( &amp;quot;Got &amp;quot; + jsFile.getSource() + &amp;#039;. File length: &amp;#039; + jsFile.get().length + &amp;#039; characters.&amp;#039; , Math.round( (len - pendings)*(9/len) ) + 10, jsFile );&lt;br /&gt;
				&lt;br /&gt;
				if (pendings) return;&lt;br /&gt;
				process.process();&lt;br /&gt;
			},&lt;br /&gt;
			gotJSErr: function(jsFile) {&lt;br /&gt;
				$progress.reject( &amp;quot;Failed. Could not retrieve &amp;quot; + jsFile.getSource(), -1, jsFile );&lt;br /&gt;
			},&lt;br /&gt;
			getStartBlock: function(sig) {&lt;br /&gt;
				// String concat is sloooow&lt;br /&gt;
				return &amp;#039;//&amp;#039; + sig + new Array(48 - 2 - sig.length + 1).join(&amp;#039;/&amp;#039;);&lt;br /&gt;
			},&lt;br /&gt;
			getEndBlock: function(sig) {&lt;br /&gt;
				return new Array(48 - 2 - 3 - sig.length + 1).join(&amp;#039;/&amp;#039;) + sig + &amp;#039;End&amp;#039; + &amp;#039;//&amp;#039;;&lt;br /&gt;
			},&lt;br /&gt;
			getBlockRegExp: function(sig) {&lt;br /&gt;
				var escSig = process.escapeRE(sig);&lt;br /&gt;
				return new RegExp(&amp;#039;\\n?\\n?\\/\\/&amp;#039; + escSig + &amp;#039;(?:.|\\n)*&amp;#039; + escSig + &amp;#039;End\\/\\/&amp;#039;, &amp;#039;g&amp;#039;);&lt;br /&gt;
			},&lt;br /&gt;
			escapeRE: function(string) {&lt;br /&gt;
				string = mw.RegExp.escape(string);&lt;br /&gt;
				&lt;br /&gt;
				var specials = [&amp;#039;t&amp;#039;, &amp;#039;n&amp;#039;, &amp;#039;v&amp;#039;, &amp;#039;0&amp;#039;, &amp;#039;f&amp;#039;];&lt;br /&gt;
				$.each(specials, function(i, s) {&lt;br /&gt;
					var rx = new RegExp(&amp;#039;\\&amp;#039;+s, &amp;#039;g&amp;#039;);&lt;br /&gt;
					string = string.replace(rx, &amp;#039;\\&amp;#039;+s);&lt;br /&gt;
				});&lt;br /&gt;
				return string;&lt;br /&gt;
			},&lt;br /&gt;
			getVariableRegExp: function(varName) {&lt;br /&gt;
				var escVar = process.escapeRE(varName);&lt;br /&gt;
				return {&lt;br /&gt;
					varRE: new RegExp(&amp;#039;\\s*(?:var\\s+|window\\.)?&amp;#039; + escVar + &amp;#039;\\s*=.+&amp;#039;, &amp;#039;g&amp;#039;),&lt;br /&gt;
					// Throw a warning if the last char of the line is a &amp;quot;+&amp;quot; , &amp;quot;{&amp;quot;, &amp;quot;(&amp;quot; or &amp;quot;,&amp;quot;&lt;br /&gt;
					varWarnRE: new RegExp(&amp;#039;\\s*(?:var\\s+|window\\.)?&amp;#039; + escVar + &amp;#039;\\s*=.+(?:\\n?\\s*[\\,\\+\\{\\(])\\s*\\n&amp;#039;)&lt;br /&gt;
				};&lt;br /&gt;
			},&lt;br /&gt;
			process: function() {&lt;br /&gt;
				var JSONVal = JSON.stringify( specs.value ),&lt;br /&gt;
					sig = specs.encloseSignature,&lt;br /&gt;
					tsa = specs.triggerSaveAt,&lt;br /&gt;
					opn = specs.optionName,&lt;br /&gt;
					jsFile, i, len = jsFiles.length,&lt;br /&gt;
					plainJSON = !opn &amp;amp;&amp;amp; !!jsFile,&lt;br /&gt;
					oldText, newText, hadMatch;&lt;br /&gt;
				&lt;br /&gt;
				if (opn) {&lt;br /&gt;
					// No semicolon for valid JSON!&lt;br /&gt;
					JSONVal = &amp;#039;window.&amp;#039; + opn + &amp;#039; = &amp;#039; + JSONVal + &amp;#039;;&amp;#039;;&lt;br /&gt;
				}&lt;br /&gt;
				&lt;br /&gt;
				if (!plainJSON) JSONVal = ((specs.encloseBlock &amp;amp;&amp;amp; (&amp;#039;\n&amp;#039; + specs.encloseBlock)) || &amp;#039;&amp;#039;) + JSONVal;&lt;br /&gt;
				&lt;br /&gt;
				if (sig &amp;amp;&amp;amp; !plainJSON) JSONVal = process.getStartBlock( sig ) + JSONVal + &amp;#039;\n&amp;#039; + process.getEndBlock( sig );&lt;br /&gt;
				&lt;br /&gt;
				JSONVal = &amp;#039;\n\n&amp;#039; + JSONVal;&lt;br /&gt;
				&lt;br /&gt;
				// Fine, we&amp;#039;ve constructed everything we&amp;#039;ll need. Now look up where to insert.&lt;br /&gt;
				// Looking for signature&lt;br /&gt;
				if (sig) {&lt;br /&gt;
					var reBl = process.getBlockRegExp( sig );&lt;br /&gt;
						&lt;br /&gt;
					for (i = 0; i &amp;lt; len; i++) {&lt;br /&gt;
						jsFile = jsFiles[i];&lt;br /&gt;
						oldText = jsFile.get();&lt;br /&gt;
						newText = oldText.replace( reBl, JSONVal );&lt;br /&gt;
						if (reBl.test( oldText )) {&lt;br /&gt;
							$progress.notify( &amp;quot;Replacing text enclosed by signature &amp;quot; + jsFile.getSource(), 25, jsFile );&lt;br /&gt;
							process.save( jsFile.set( newText ) );&lt;br /&gt;
							hadMatch = true;&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				if (hadMatch) return;&lt;br /&gt;
				&lt;br /&gt;
				// Looking for variable-name&lt;br /&gt;
				if (opn) {&lt;br /&gt;
					var vre = process.getVariableRegExp( opn ),&lt;br /&gt;
						warnFile;&lt;br /&gt;
					&lt;br /&gt;
					for (i = 0; i &amp;lt; len; i++) {&lt;br /&gt;
						jsFile = jsFiles[i];&lt;br /&gt;
						oldText = jsFile.get();&lt;br /&gt;
						&lt;br /&gt;
						if (vre.varWarnRE.test(oldText)) {&lt;br /&gt;
							// WARNING!!!&lt;br /&gt;
							$progress.notify( &amp;quot;Unable to remove config from &amp;quot; + jsFile.getSource(), -2, jsFile );&lt;br /&gt;
							warnFile = jsFile;&lt;br /&gt;
						} else {&lt;br /&gt;
							newText = oldText.replace( vre.varRE, JSONVal );&lt;br /&gt;
							if (vre.varRE.test( oldText )) {&lt;br /&gt;
								$progress.notify( &amp;quot;Replacing variable &amp;quot; + jsFile.getSource(), 25, jsFile );&lt;br /&gt;
								process.save( jsFile.set( newText ) );&lt;br /&gt;
								hadMatch = true;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						// Only append in case of warning if it was not added to another file&lt;br /&gt;
						if (warnFile &amp;amp;&amp;amp; !hadMatch) {&lt;br /&gt;
							$progress.notify( &amp;quot;Appending variable after warning to &amp;quot; + jsFile.getSource(), 25, jsFile );&lt;br /&gt;
							process.save( warnFile.set( oldText + JSONVal ) );&lt;br /&gt;
							hadMatch = true;&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				if (hadMatch) return;&lt;br /&gt;
				&lt;br /&gt;
				// If it&amp;#039;s just JSON, replace the whole thingy&lt;br /&gt;
				if (!opn &amp;amp;&amp;amp; specs.saveAt) {&lt;br /&gt;
					jsFile = jsFiles[0];&lt;br /&gt;
					$progress.notify( &amp;quot;Replacing whole content of &amp;quot; + jsFile.getSource(), 25, jsFile );&lt;br /&gt;
					process.save( jsFile.set( JSONVal ) );&lt;br /&gt;
					hadMatch = true;&lt;br /&gt;
				}&lt;br /&gt;
				if (hadMatch) return;&lt;br /&gt;
				&lt;br /&gt;
				// Looking whether supplied RegExp can find something&lt;br /&gt;
				if (tsa) {&lt;br /&gt;
					var searchMatch,&lt;br /&gt;
						triggerLen = 0;&lt;br /&gt;
					&lt;br /&gt;
					for (i = 0; i &amp;lt; len; i++) {&lt;br /&gt;
						jsFile = jsFiles[i];&lt;br /&gt;
						oldText = jsFile.get();&lt;br /&gt;
						&lt;br /&gt;
						searchMatch = oldText.search( tsa );&lt;br /&gt;
						if (-1 !== searchMatch) {&lt;br /&gt;
							if (specs.insertBeforeTrigger) {&lt;br /&gt;
								$progress.notify( &amp;quot;Inserting before pattern in &amp;quot; + jsFile.getSource(), 25, jsFile );&lt;br /&gt;
								jsFile.set( oldText.slice( 0, searchMatch ) + JSONVal + oldText.slice( searchMatch ) );&lt;br /&gt;
							} else if (specs.insertAfterTrigger) {&lt;br /&gt;
								triggerLen = oldText.match( tsa )[0].length;&lt;br /&gt;
								$progress.notify( &amp;quot;Inserting after pattern in &amp;quot; + jsFile.getSource(), 25, jsFile );&lt;br /&gt;
								jsFile.set( oldText.slice( 0, searchMatch + triggerLen ) + JSONVal + oldText.slice( searchMatch + triggerLen ) );&lt;br /&gt;
							} else if (specs.replaceTrigger) {&lt;br /&gt;
								$progress.notify( &amp;quot;Replacing pattern with new content in &amp;quot; + jsFile.getSource(), 25, jsFile );&lt;br /&gt;
								jsFile.set( oldText.replace( tsa, JSONVal ) );&lt;br /&gt;
							} else {&lt;br /&gt;
								$progress.notify( &amp;quot;Found pattern, appending to &amp;quot; + jsFile.getSource(), 25, jsFile );&lt;br /&gt;
								jsFile.set( oldText + &amp;#039;\n//&amp;lt;nowiki&amp;gt;&amp;#039; + JSONVal + &amp;#039;\n//&amp;lt;\/nowiki&amp;gt;&amp;#039; );&lt;br /&gt;
							}&lt;br /&gt;
							process.save( jsFile );&lt;br /&gt;
							hadMatch = true;&lt;br /&gt;
							break;&lt;br /&gt;
						}&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				if (hadMatch) return;&lt;br /&gt;
				&lt;br /&gt;
				// Finally compare file size&lt;br /&gt;
				var biggest = { size: 0, jsFile: null };&lt;br /&gt;
					&lt;br /&gt;
				for (i = 0; i &amp;lt; len; i++) {&lt;br /&gt;
					jsFile = jsFiles[i];&lt;br /&gt;
					oldText = jsFile.get();&lt;br /&gt;
					var oldTextLen = oldText.length;&lt;br /&gt;
					&lt;br /&gt;
					if (oldTextLen &amp;gt;= biggest.size) biggest = {&lt;br /&gt;
						size: oldTextLen,&lt;br /&gt;
						jsFile: jsFile&lt;br /&gt;
					};&lt;br /&gt;
				}&lt;br /&gt;
				$progress.notify( &amp;quot;Appending to bigger file: &amp;quot; + biggest.jsFile.getSource(), 25, biggest.jsFile );&lt;br /&gt;
				biggest.jsFile.set( biggest.jsFile.get() + &amp;#039;\n//&amp;lt;nowiki&amp;gt;&amp;#039; + JSONVal + &amp;#039;\n//&amp;lt;\/nowiki&amp;gt;&amp;#039; );&lt;br /&gt;
				process.save( biggest.jsFile );&lt;br /&gt;
			},&lt;br /&gt;
			save: function(jsFile) {&lt;br /&gt;
				jsFile.saving = true;&lt;br /&gt;
				$progress.notify( &amp;quot;Saving &amp;quot; + jsFile.getSource(), 30, jsFile );&lt;br /&gt;
				jsFile.save( process.saved, process.savedErr, &amp;quot;[[MediaWiki:Gadget-SettingsManager.js|SettingsManager]]: &amp;quot; + specs.editSummary );&lt;br /&gt;
			},&lt;br /&gt;
			saved: function(jsFile) {&lt;br /&gt;
				var i, len = jsFiles.length, jsf, waitingFor = [];&lt;br /&gt;
				&lt;br /&gt;
				jsFile.saving = false;&lt;br /&gt;
				&lt;br /&gt;
				for (i = 0; i &amp;lt; len; i++) {&lt;br /&gt;
					jsf = jsFiles[i];&lt;br /&gt;
					if (jsf.saving) {&lt;br /&gt;
						waitingFor.push(jsf.getSource());&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				$progress.notify( &amp;quot;Saved &amp;quot; + jsFile.getSource() + &amp;quot;. Waiting for &amp;quot; + (waitingFor.join(&amp;#039;, &amp;#039;) || &amp;#039;-&amp;#039;), Math.round( (len - waitingFor.length)*(20/len) ) + 50,  jsFile );&lt;br /&gt;
				&lt;br /&gt;
				if (waitingFor.length) return;&lt;br /&gt;
				$progress.resolve( &amp;quot;Success!&amp;quot;, 100, jsFile );&lt;br /&gt;
			},&lt;br /&gt;
			savedErr: function(jsFile, code, errObj) {&lt;br /&gt;
				$progress.reject( &amp;quot;Error saving &amp;quot; + jsFile.getSource() + &amp;quot;. Code is &amp;quot; + code + &amp;quot;.\n&amp;quot;, -1, errObj );&lt;br /&gt;
			}&lt;br /&gt;
		};&lt;br /&gt;
		&lt;br /&gt;
		return {&lt;br /&gt;
			getSpecs: function() {&lt;br /&gt;
				return specs;&lt;br /&gt;
			},&lt;br /&gt;
			setSpecs: function(specsIn) {&lt;br /&gt;
				specs = specsIn;&lt;br /&gt;
				return this;&lt;br /&gt;
			},&lt;br /&gt;
			// Warning: If you specified a different save-position (&amp;quot;saveAt&amp;quot;)&lt;br /&gt;
			// and also an optionName, the script has to be fetched and evaluated&lt;br /&gt;
			// We recommend omitting setting &amp;quot;optionName&amp;quot; when using &amp;quot;saveAt&amp;quot;&lt;br /&gt;
			fetchValue: function(cb, errCb) {&lt;br /&gt;
				process.updateVars();&lt;br /&gt;
				&lt;br /&gt;
				if (specs.saveAt) {&lt;br /&gt;
					var s = sm.script( customJS );&lt;br /&gt;
					if (specs.optionName) {&lt;br /&gt;
						s.fetchText(function() {&lt;br /&gt;
							s.doEval();&lt;br /&gt;
							cb( valByString( specs.optionName ) );&lt;br /&gt;
						}, errCb);&lt;br /&gt;
					} else {&lt;br /&gt;
						s.fetchJSON(function(scriptObj, JSON) {&lt;br /&gt;
							cb( JSON );&lt;br /&gt;
						}, errCb);&lt;br /&gt;
					}&lt;br /&gt;
					return this;&lt;br /&gt;
				}&lt;br /&gt;
				cb( valByString( specs.optionName ) );&lt;br /&gt;
				return this;&lt;br /&gt;
			},&lt;br /&gt;
			getValue: function() {&lt;br /&gt;
				return specs.value;&lt;br /&gt;
			},&lt;br /&gt;
			setValue: function(val) {&lt;br /&gt;
				specs.value = val;&lt;br /&gt;
				return this;&lt;br /&gt;
			},&lt;br /&gt;
			save: function($elem, event) {&lt;br /&gt;
				// We won&amp;#039;t check whether the value is undefined. This is your task.&lt;br /&gt;
				$el = $elem;&lt;br /&gt;
				evt = event;&lt;br /&gt;
				return process.start();&lt;br /&gt;
			},&lt;br /&gt;
			getProgress: function() {&lt;br /&gt;
				return $progress;&lt;br /&gt;
			}&lt;br /&gt;
		};&lt;br /&gt;
	},&lt;br /&gt;
	/**&lt;br /&gt;
	* Constructor-method. Returns a script-object you should perform the actions on.&lt;br /&gt;
	*&lt;br /&gt;
	* @example&lt;br /&gt;
	*      var commonJS = mw.libs.settingsManager.script( &amp;#039;User:Example/common.js&amp;#039; );&lt;br /&gt;
	*      commonJS.set( &amp;#039;// empty!&amp;#039; ).setSummary( &amp;#039;Removing Content&amp;#039; ).save( function() { console.log( &amp;#039;Successfully removed content from &amp;#039; + commonJS.getSource() ) } )&lt;br /&gt;
	*&lt;br /&gt;
	* @param source {String} The name of the JavaScript file with namespace.&lt;br /&gt;
	* @context {mw.libs.settingsManager}&lt;br /&gt;
	* @return {Object} script-object you can use for performing actions on.&lt;br /&gt;
	*/&lt;br /&gt;
	script: function(source) {&lt;br /&gt;
		var content,&lt;br /&gt;
			page,&lt;br /&gt;
			summary = &amp;quot;Changing configuration using [[:commons:MediaWiki:Gadget-SettingsManager.js]]&amp;quot;,&lt;br /&gt;
			minor = 1,&lt;br /&gt;
			exists,&lt;br /&gt;
			fetch,&lt;br /&gt;
			save;&lt;br /&gt;
&lt;br /&gt;
		fetch = function() {&lt;br /&gt;
			var mwa = new mw.Api();&lt;br /&gt;
			return mwa.get( {&lt;br /&gt;
				prop: &amp;#039;info|revisions&amp;#039;,&lt;br /&gt;
				titles: source,&lt;br /&gt;
				rvprop: &amp;#039;timestamp|content&amp;#039;,&lt;br /&gt;
				intoken: &amp;#039;edit&amp;#039;&lt;br /&gt;
			} );&lt;br /&gt;
		};&lt;br /&gt;
		&lt;br /&gt;
		save = function() {&lt;br /&gt;
			var mwa = new mw.Api(),&lt;br /&gt;
				edit = {&lt;br /&gt;
					action: &amp;#039;edit&amp;#039;,&lt;br /&gt;
					title: source,&lt;br /&gt;
					text: &amp;#039;object&amp;#039; === typeof content ? JSON.stringify(content) : content,&lt;br /&gt;
					summary: summary,&lt;br /&gt;
					watchlist: &amp;#039;nochange&amp;#039;,&lt;br /&gt;
					recreate: 1&lt;br /&gt;
				};&lt;br /&gt;
				&lt;br /&gt;
			if (minor) edit.minor = 1;&lt;br /&gt;
			if (exists) {&lt;br /&gt;
				edit.basetimestamp = page.revisions[0].timestamp;&lt;br /&gt;
			} else {&lt;br /&gt;
				edit.starttimestamp = page.starttimestamp;&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			edit.token = page.edittoken;&lt;br /&gt;
			return mwa.post( edit );&lt;br /&gt;
		};&lt;br /&gt;
			&lt;br /&gt;
		return {&lt;br /&gt;
			get: function() {&lt;br /&gt;
				return content;&lt;br /&gt;
			},&lt;br /&gt;
			getSource: function() {&lt;br /&gt;
				return source;&lt;br /&gt;
			},&lt;br /&gt;
			doEval: function() {&lt;br /&gt;
				/*jshint evil:true */&lt;br /&gt;
				return eval(content);&lt;br /&gt;
			},&lt;br /&gt;
			parseJSON: function() {&lt;br /&gt;
				return (&amp;#039;string&amp;#039; === typeof content &amp;amp;&amp;amp; content !== &amp;#039;&amp;#039;) ? JSON.parse( content ) : &amp;#039;&amp;#039;;&lt;br /&gt;
			},&lt;br /&gt;
			// Supplied callback called with a string as second argument&lt;br /&gt;
			fetchText: function(cb, errCb) {&lt;br /&gt;
				var pgs, pg, scriptObj = this;&lt;br /&gt;
				&lt;br /&gt;
				fetch().done( function(result) {&lt;br /&gt;
					pgs = result.query.pages;&lt;br /&gt;
					page = firstItem( pgs );&lt;br /&gt;
					exists = !!(page.revisions &amp;amp;&amp;amp; page.revisions[0]);&lt;br /&gt;
					content = (exists &amp;amp;&amp;amp; page.revisions[0][&amp;#039;*&amp;#039;]) || &amp;#039;&amp;#039;;&lt;br /&gt;
					cb( scriptObj, content );&lt;br /&gt;
				} ).fail( function( status, errObj ) {&lt;br /&gt;
					errCb( scriptObj, status, errObj );&lt;br /&gt;
				} );&lt;br /&gt;
				return this;&lt;br /&gt;
			},&lt;br /&gt;
			// Supplied callback called with parsed JSON-data as second argument&lt;br /&gt;
			fetchJSON: function(cb, errCb) {&lt;br /&gt;
				this.fetchText( function(scriptObj, content) {&lt;br /&gt;
					cb( scriptObj, scriptObj.parseJSON() );&lt;br /&gt;
				}, function(scriptObj, status, errObj) {&lt;br /&gt;
					errCb( scriptObj, status, errObj );&lt;br /&gt;
				} );&lt;br /&gt;
				return this;&lt;br /&gt;
			},&lt;br /&gt;
			set: function(newContent) {&lt;br /&gt;
				content = newContent;&lt;br /&gt;
				return this;&lt;br /&gt;
			},&lt;br /&gt;
			setMinor: function(newMinor) {&lt;br /&gt;
				minor = !!newMinor;&lt;br /&gt;
			},&lt;br /&gt;
			setSummary: function(newSummary) {&lt;br /&gt;
				summary = newSummary;&lt;br /&gt;
			},&lt;br /&gt;
			save: function(cb, errCb, newSummary, newContent, newMinor) {&lt;br /&gt;
				var scriptObj = this;&lt;br /&gt;
				if (newContent !== undefined) content = newContent;&lt;br /&gt;
				if (newSummary !== undefined) summary = newSummary;&lt;br /&gt;
				if (newMinor !== undefined) minor = !!newMinor;&lt;br /&gt;
				save().done( function(result) {&lt;br /&gt;
					cb( scriptObj, result );&lt;br /&gt;
				} ).fail( function(status, errObj) {&lt;br /&gt;
					errCb( scriptObj, status, errObj );&lt;br /&gt;
				} );&lt;br /&gt;
				return this;&lt;br /&gt;
			}&lt;br /&gt;
		};&lt;br /&gt;
	},&lt;br /&gt;
	/**&lt;br /&gt;
	* Switch a user preference using Ajax!&lt;br /&gt;
	*&lt;br /&gt;
	* @example&lt;br /&gt;
	*      mw.libs.settingsManager.switchPref( &amp;#039;myOption&amp;#039;, &amp;#039;new value&amp;#039; );&lt;br /&gt;
	*&lt;br /&gt;
	* @param prefName {String} The name of the preference.&lt;br /&gt;
	* @param prefVal {String} The new value the preference should set to.&lt;br /&gt;
	* @param cb {Function} Callback in case of success.&lt;br /&gt;
	* @param cb {Function} Callback in case of an error.&lt;br /&gt;
	* @context {mw.libs.settingsManager}&lt;br /&gt;
	* @return {Object} a jQuery deferred-object-queue. Don&amp;#039;t use it for error-handling - Done by this method.&lt;br /&gt;
	*/&lt;br /&gt;
	switchPref: function(prefName, prefVal, cb, errCb) {&lt;br /&gt;
		var mwa = new mw.Api(),&lt;br /&gt;
			args = arguments,&lt;br /&gt;
			prefString = (typeof prefVal === &amp;#039;object&amp;#039;) ? JSON.stringify(prefVal) : prefVal,&lt;br /&gt;
			apiDef = mwa.post( {&lt;br /&gt;
				action: &amp;#039;options&amp;#039;,&lt;br /&gt;
				token: mw.user.tokens.get(&amp;#039;preferencesToken&amp;#039;),&lt;br /&gt;
				optionname: prefName,&lt;br /&gt;
				optionvalue: prefString || 0&lt;br /&gt;
			} );&lt;br /&gt;
&lt;br /&gt;
		// If we changed a preference successfully, update user.options reflecting the change&lt;br /&gt;
		apiDef.done( function() {&lt;br /&gt;
			mw.user.options.set( prefName, prefString );&lt;br /&gt;
		} );&lt;br /&gt;
		if (cb) apiDef.done( cb );&lt;br /&gt;
		// Catch badtoken and some other common errors&lt;br /&gt;
		apiDef.fail( function(code, result) {&lt;br /&gt;
			switch (code) {&lt;br /&gt;
				case &amp;#039;badtoken&amp;#039;:&lt;br /&gt;
					refreshToken(function (gotANewToken) {&lt;br /&gt;
						if (gotANewToken) return sm.switchPref.apply( sm, Array.prototype.slice.call( args, 0 ) );&lt;br /&gt;
					} );&lt;br /&gt;
					// Stop the propagation of &lt;br /&gt;
					return false;&lt;br /&gt;
				case &amp;#039;http&amp;#039;:&lt;br /&gt;
				case &amp;#039;ok-but-empty&amp;#039;:&lt;br /&gt;
					setTimeout( function() {&lt;br /&gt;
						return sm.switchPref.apply( sm, Array.prototype.slice.call(args, 0) );&lt;br /&gt;
					}, 2500 );&lt;br /&gt;
					return false;&lt;br /&gt;
				default:&lt;br /&gt;
					return (errCb &amp;amp;&amp;amp; errCb(code, result) &amp;amp;&amp;amp; false);&lt;br /&gt;
			}&lt;br /&gt;
		} );&lt;br /&gt;
		return apiDef;&lt;br /&gt;
	},&lt;br /&gt;
	/**&lt;br /&gt;
	* Switch a gadget preference using Ajax!&lt;br /&gt;
	*&lt;br /&gt;
	* @example&lt;br /&gt;
	*      mw.libs.settingsManager.switchGadgetPref( &amp;#039;myOption&amp;#039;, &amp;#039;new value&amp;#039; ).done(function() { console.log(&amp;quot;DONE!&amp;quot;) });&lt;br /&gt;
	*&lt;br /&gt;
	* @param prefName {String} The name of the preference.&lt;br /&gt;
	* @param prefVal {String} The new value the preference should set to.&lt;br /&gt;
	* @context {mw.libs.settingsManager}&lt;br /&gt;
	* @return {Object} $.Deferred; a jQuery deferred-object-queue.&lt;br /&gt;
	*/&lt;br /&gt;
	switchGadgetPref: function(prefName, prefVal) {&lt;br /&gt;
		var $def = $.Deferred();&lt;br /&gt;
&lt;br /&gt;
		sm.switchPref( mwPrefPrefix + prefName, prefVal, $.proxy( $def.resolve, $def ), $.proxy( $def.reject, $def ) );&lt;br /&gt;
		return $def;&lt;br /&gt;
	},&lt;br /&gt;
	&lt;br /&gt;
	/**&lt;br /&gt;
	* Fetch a Gadget preference from various sources!&lt;br /&gt;
	*&lt;br /&gt;
	* @example&lt;br /&gt;
	*      mw.libs.settingsManager.fetchGadgetSetting( &amp;#039;mySetting&amp;#039;, [&amp;#039;storage&amp;#039;, &amp;#039;option&amp;#039;] ).done(function(prefName, settingValue) { console.log(&amp;quot;DONE!&amp;quot;) });&lt;br /&gt;
	*&lt;br /&gt;
	* @param prefName {String} The name of the preference.&lt;br /&gt;
	* @param prefSources {Array} One or more of the following values &amp;#039;storage&amp;#039;, &amp;#039;cookie&amp;#039;, &amp;#039;option&amp;#039;, &amp;#039;window&amp;#039;. Default (if not passed): &lt;br /&gt;
	*                             All in the order listed there. Note that they are processed in the order you pass them in and as soon as one is found,&lt;br /&gt;
	*                             Script will return.&lt;br /&gt;
	*                             IMPORTANT: The Array is changed while processing. So make a copy if you need it again before passing it.&lt;br /&gt;
	*&lt;br /&gt;
	* @context {mw.libs.settingsManager}&lt;br /&gt;
	* @return {Object} $.Deferred; a jQuery deferred-object-queue.&lt;br /&gt;
	*/&lt;br /&gt;
	fetchGadgetSetting: function(prefName, prefSources) {&lt;br /&gt;
		var $def = $.Deferred(), requires = [], options = {&lt;br /&gt;
			&amp;#039;storage&amp;#039;: {&lt;br /&gt;
				requires: [&amp;#039;jquery.jStorage&amp;#039;],&lt;br /&gt;
				fetch: function() {&lt;br /&gt;
					var v = $.jStorage.get( prefName );&lt;br /&gt;
					return (null === v || undefined === v) ? undefined : v;&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
			&amp;#039;cookie&amp;#039;: {&lt;br /&gt;
				requires: [&amp;#039;jquery.cookie&amp;#039;],&lt;br /&gt;
				fetch: function() {&lt;br /&gt;
					var v = $.cookie( prefName );&lt;br /&gt;
					try {&lt;br /&gt;
						v = JSON.parse( v );&lt;br /&gt;
					} catch(invalidJSON) {}&lt;br /&gt;
					return (null === v || undefined === v) ? undefined : v;&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
			&amp;#039;option&amp;#039;: {&lt;br /&gt;
				requires: [&amp;#039;mediawiki.user&amp;#039;, &amp;#039;user.options&amp;#039;],&lt;br /&gt;
				fetch: function() {&lt;br /&gt;
					var v = mw.user.options.get( mwPrefPrefix + prefName );&lt;br /&gt;
					try {&lt;br /&gt;
						v = JSON.parse( v );&lt;br /&gt;
					} catch(invalidJSON) {}&lt;br /&gt;
					return (null === v || undefined === v) ? undefined : v;&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
			&amp;#039;window&amp;#039;: {&lt;br /&gt;
				requires: [],&lt;br /&gt;
				fetch: function() {&lt;br /&gt;
					return window[prefName];&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		};&lt;br /&gt;
		if (!prefSources) prefSources = [];&lt;br /&gt;
		if (!prefSources.length) prefSources = [&amp;#039;storage&amp;#039;, &amp;#039;cookie&amp;#039;, &amp;#039;option&amp;#039;, &amp;#039;window&amp;#039;];&lt;br /&gt;
		&lt;br /&gt;
		var _fetch = function(s) {&lt;br /&gt;
				var so = options[s];&lt;br /&gt;
				if (so) {&lt;br /&gt;
					mw.loader.using( so.requires, function() {&lt;br /&gt;
						var v = so.fetch();&lt;br /&gt;
						if (undefined === v) {&lt;br /&gt;
							_fetched();&lt;br /&gt;
						} else {&lt;br /&gt;
							$def.resolve( prefName, v );&lt;br /&gt;
						}&lt;br /&gt;
					} );&lt;br /&gt;
				} else {&lt;br /&gt;
					// Security guard: Don&amp;#039;t load settings from unprotected pages&lt;br /&gt;
					if (!/^(?:User\:|MediaWiki\:).+\.js$/.test( s )) _fetched();&lt;br /&gt;
					sm.script( s ).fetchJSON( function(me, jsonData) {&lt;br /&gt;
						if (jsonData) {&lt;br /&gt;
							$def.resolve( prefName, jsonData );&lt;br /&gt;
						} else {&lt;br /&gt;
							_fetched();&lt;br /&gt;
						}&lt;br /&gt;
					}, $.proxy( $def.reject, $def ) );&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
			_fetched = function() {&lt;br /&gt;
				prefSources.shift();&lt;br /&gt;
				if (prefSources.length) {&lt;br /&gt;
					_fetch( prefSources[0] );&lt;br /&gt;
				} else {&lt;br /&gt;
					$def.resolve( prefName /* no pref found */ );&lt;br /&gt;
				}&lt;br /&gt;
			};&lt;br /&gt;
			&lt;br /&gt;
		$.each( prefSources, function(i, s) {&lt;br /&gt;
			var so = options[s];&lt;br /&gt;
			if (so) requires = requires.concat( options[s].requires );&lt;br /&gt;
		} );&lt;br /&gt;
		mw.loader.load( requires );&lt;br /&gt;
			&lt;br /&gt;
		// ensure async&lt;br /&gt;
		setTimeout( function() {&lt;br /&gt;
			_fetch(prefSources[0]);&lt;br /&gt;
		}, 10 );&lt;br /&gt;
		&lt;br /&gt;
		return $def;&lt;br /&gt;
	},&lt;br /&gt;
	&lt;br /&gt;
	/**&lt;br /&gt;
	* Constructor-method. Returns an option-object you should perform the actions on.&lt;br /&gt;
	*&lt;br /&gt;
	* @example&lt;br /&gt;
	*      var slideshowGadget = mw.libs.settingsManager.gadget( &amp;#039;Slideshow&amp;#039; );&lt;br /&gt;
	*      if (slideshowGadget.isEnabled()) { slideshowGadget.disable( myCallback ) }&lt;br /&gt;
	*&lt;br /&gt;
	*      // Enable a gadget and load it:&lt;br /&gt;
	*      mw.libs.settingsManager.gadget( &amp;#039;Slideshow&amp;#039; ).load().enable();&lt;br /&gt;
	*&lt;br /&gt;
	* @param gadgetName {Object} The name of the gadget. (Not the script file; without Gadget- prefix or other decoration)&lt;br /&gt;
	* @context {mw.libs.settingsManager}&lt;br /&gt;
	* @return {Object} gadget-object you can use for performing actions on.&lt;br /&gt;
	*/&lt;br /&gt;
	gadget: function(gadgetName) {&lt;br /&gt;
		var optGadget = &amp;#039;gadget-&amp;#039; + gadgetName,&lt;br /&gt;
			rlGadget = &amp;#039;ext.gadget.&amp;#039; + gadgetName;&lt;br /&gt;
			&lt;br /&gt;
		return {&lt;br /&gt;
			getName: function() {&lt;br /&gt;
				return gadgetName;&lt;br /&gt;
			},&lt;br /&gt;
			isDefault: function() {&lt;br /&gt;
				var opt = mw.user.options.get( optGadget );&lt;br /&gt;
				return (&amp;#039;number&amp;#039; === typeof opt || &amp;#039;&amp;#039; === opt);&lt;br /&gt;
			},&lt;br /&gt;
			isEnabled: function() {&lt;br /&gt;
				var opt = mw.user.options.get( optGadget );&lt;br /&gt;
				return !!opt;&lt;br /&gt;
			},&lt;br /&gt;
			getState: function() {&lt;br /&gt;
				return mw.loader.getState( rlGadget );&lt;br /&gt;
			},&lt;br /&gt;
			isLoaded: function() {&lt;br /&gt;
				return (&amp;#039;ready&amp;#039; === this.getState());&lt;br /&gt;
			},&lt;br /&gt;
			load: function(cb, errCb) {&lt;br /&gt;
				// Always async&lt;br /&gt;
				if (this.isLoaded &amp;amp;&amp;amp; cb) return setTimeout( function() {&lt;br /&gt;
					cb( gadgetName, true );&lt;br /&gt;
				}, 1 );&lt;br /&gt;
				mw.loader.using( rlGadget, &lt;br /&gt;
					cb ? function() { &lt;br /&gt;
						cb( gadgetName ); &lt;br /&gt;
					} : undefined, &lt;br /&gt;
					errCb ? function() { &lt;br /&gt;
						errCb( gadgetName ); &lt;br /&gt;
					} : undefined &lt;br /&gt;
				);&lt;br /&gt;
				return this;&lt;br /&gt;
			},&lt;br /&gt;
			enable: function(cb, errCb) {&lt;br /&gt;
				// Type wouldn&amp;#039;t matter due to URL-encoding but we also want to update&lt;br /&gt;
				// the user.options object&lt;br /&gt;
				sm.switchPref( optGadget, this.isDefault() ? 1 : &amp;#039;1&amp;#039;, cb, errCb );&lt;br /&gt;
				return this;&lt;br /&gt;
			},&lt;br /&gt;
			disable: function(cb, errCb) {&lt;br /&gt;
				sm.switchPref( optGadget, &amp;#039;&amp;#039;, cb, errCb );&lt;br /&gt;
				return this;&lt;br /&gt;
			}&lt;br /&gt;
		};&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
mw.libs.settingsManager = sm;&lt;br /&gt;
&lt;br /&gt;
// TODO add to gadget-def&lt;br /&gt;
// mw.loader.load([&amp;#039;json&amp;#039;, &amp;#039;mediawiki.user&amp;#039;, &amp;#039;user.options&amp;#039;, &amp;#039;user.tokens&amp;#039;]);&lt;br /&gt;
}( jQuery, mediaWiki ));&lt;/div&gt;</summary>
		<author><name>admin&gt;Nazarzadeh</name></author>
	</entry>
</feed>