MediaWiki:Gadget-WiktGadgetPrefs.js
Jump to navigation
Jump to search
Note: You may have to bypass your browser’s cache to see the changes. In addition, after saving a sitewide CSS file such as MediaWiki:Common.css, it will take 5-10 minutes before the changes take effect, even if you clear your cache.
- Mozilla / Firefox / Safari: hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (Command-R on a Macintosh);
- Konqueror and Chrome: click Reload or press F5;
- Opera: clear the cache in Tools → Preferences;
- Internet Explorer: hold Ctrl while clicking Refresh, or press Ctrl-F5.
- The following documentation is located at MediaWiki:Gadget-WiktGadgetPrefs.js/documentation. [edit]
- This script is a part of the
WiktGadgetPrefs
gadget (edit definitions)- Description (edit): Gadget preferences
- Useful links: subpage list • links • redirects
Provides a framework for gadgets to store additional preferences, both for registered and anonymous users.
MediaWiki:Gadget-WiktGadgetPrefsPage.js implements Wiktionary:Gadget preferences, which is where these preferences can be modified.
See also: Special:Gadgets.
/* global mw */
// <nowiki>
/*jshint shadow:true, undef:true, latedef:true, unused:true, esversion:3 */
/**
* WiktGadgetPrefs -- developed by [[wikt:en:User:Surjection]]
*
* Example usage (remember to add ext.gadget.WiktGadgetPrefs as a dependency):
var preferences = mw.wiktGadgetPrefs.get("gadgetfoobar",
{
"label": {
"en": "Foobar Gadget"
}
},
{
"frobulate": {
"type": "boolean",
"default": false,
"label": {
"en": "Whether this gadget should frobulate"
}
}
});
var shouldFrobulate = preferences.frobulate;
// strenum example
var preferences = mw.wiktGadgetPrefs.get("gadgetfoobar",
{
"label": {
"en": "Foobar Gadget"
}
},
{
"frobulate": {
"type": "strenum",
"default": "yes",
"label": {
"en": "Whether this gadget should frobulate"
},
"choices": [
"yes",
"no",
"maybe"
],
"choiceLabels": {
"en": {
"yes": "Yes!",
"no": "No!!",
"maybe": "Maybe?"
}
}
}
});
var shouldFrobulate = preferences.frobulate;
* Dependencies needed: mw.user, user.options
*/
(function() {
"use strict";
/**
* @typedef WiktGadgetOptions
* - Represents gadget options.
* @property {{[languageCode: string]: string}} [label]
* - The label to display on the preferences page for this
* gadget/namespace. The language code should be a MediaWiki
* language code, e.g. "en" for English.
*/
/**
* @typedef WiktGadgetPreference
* - Represents a single preference.
* @property {{"boolean"|"integer"|"string"|"strenum"|"object"}} type
* - Must be one of the following:
* - "boolean" for boolean values, either true or false.
* - "integer" for an integer value.
* - "string" for a string value.
* - "strenum" for a string value that must be one of the options.
* - "object" for an arbitrary JSON value, including null.
* No type checks are done.
* @property {any} default
* - The default value for this preference if missing, or if
* the value is invalid.
* - The developer is responsible for ensuring that this value is
* given, and that it meets the preconditions defined below.
* @property {string[]} [choices]
* - If the type is "strenum", then this must be an array of
* allowed options. If the value is not in this list, the default
* value will be returned.
* @property {number} [minimum]
* - If the type is "integer", this is the minimum allowed value.
* @property {number} [maximum]
* - If the type is "integer", this is the maximum allowed value.
* @property {number} [maximumLength]
* - If the type is "string", this is the maximum allowed length.
* @property {{[languageCode: string]: string}} [label]
* - The label to display on the preferences page for this
* preference. The language code should be a MediaWiki
* language code, e.g. "en" for English.
* @property {{[languageCode: string]: {[choice: string]: string}}} [choiceLabels]
* - The label to display on the preferences page for the choices
* of this preference (if it is an enum type). The language code
* should be a MediaWiki language code, e.g. "en" for English.
*/
var wiktGadgetPrefs__registeredPrefs = {};
var wiktGadgetPrefs__error = (Error ?
function (message) {
return new Error(message);
} :
function (message) {
return message;
});
var wiktGadgetPrefs__asciify = function (text) {
return text.replace(/[^A-Za-z0-9-]/g, function (match) {
if (match == "_") {
return "__";
} else {
return "_" + match.charCodeAt(0).toString(16) + "_";
}
});
};
var wiktGadgetPrefs__namespace_to_key = function (namespace) {
return "wiktgadgetprefs-" + wiktGadgetPrefs__asciify(namespace);
};
var wiktGadgetPrefs__is_integer = function (num) {
return num == (num | 0);
};
var wiktGadgetPrefs__parse_one = function (value, preference, key) {
var defaultValue = preference["default"];
switch (preference.type) {
case "boolean":
// data type
if (typeof value != "boolean") return defaultValue;
return value;
case "integer":
// data type
if (typeof value != "number") return defaultValue;
// integer check
if (!wiktGadgetPrefs__is_integer(value)) return defaultValue;
// constraints
if ((preference.minimum != null && value < preference.minimum) ||
(preference.maximum != null && value > preference.maximum))
return defaultValue;
return value;
case "string":
// data type
if (typeof value != "string") return defaultValue;
// constraints
if (preference.maximumLength != null && value.length > preference.maximumLength)
return defaultValue;
return value;
case "strenum":
// data type
if (typeof value != "string") return defaultValue;
// constraints
if (preference.choices.indexOf(value) < 0)
return defaultValue;
return value;
case "object":
if (typeof value == "undefined") return defaultValue;
return value;
}
throw wiktGadgetPrefs__error("Invalid preference specification '" + key + "'");
};
var wiktGadgetPrefs__parse_all = function (values, preferences) {
var parsed = {};
if (!values) values = {};
for (var key in preferences) {
if (preferences.hasOwnProperty(key)) {
parsed[key] = wiktGadgetPrefs__parse_one(values[key], preferences[key], key);
}
}
return parsed;
};
var wiktGadgetPrefs__resolve = function (namespaceKey, preferences) {
var resolved;
var mwOptions;
try {
mwOptions = mw.user.options;
} catch (e) {
}
if (!resolved && window.localStorage && window.localStorage.getItem("anon" + namespaceKey) != null) {
try {
resolved = JSON.parse(window.localStorage.getItem("anon" + namespaceKey));
} catch (e) { }
}
if (!resolved && mwOptions && mwOptions.exists("userjs-" + namespaceKey)) {
try {
resolved = JSON.parse(mwOptions.get("userjs-" + namespaceKey));
} catch (e) { }
}
return wiktGadgetPrefs__parse_all(resolved || {}, preferences);
};
/**
* Resolve preferences.
*
* Note that there is a maximum length imposed by MediaWiki
* on the total size of the preferences for each namespace.
*
* @param {string} namespace
* - An arbitrary string. This should be unique to each gadget.
* @param {WiktGadgetOptions} options
* - Options.
* @param {{[key: string]: WiktGadgetPreference}} preferences
* - Requested preferences, indexed by name.
* @returns {{[key: string]: any}}
*/
var wiktGadgetPrefs_get = function (namespace, options, preferences) {
if (wiktGadgetPrefs__registeredPrefs[namespace]) {
throw wiktGadgetPrefs__error("wiktGadgetPrefs_get has already been called with the namespace '" + namespace + "'.");
}
wiktGadgetPrefs__registeredPrefs[namespace] = {
options: options,
preferences: preferences
};
var namespaceKey = wiktGadgetPrefs__namespace_to_key(namespace);
if (namespaceKey.length >= 240) {
throw wiktGadgetPrefs__error("Namespace key '" + namespace + "' is too long. " +
"Please prefer ASCII characters A-Z, a-z, 0-9 and the hyphen, " +
"as other characters need to be converted, which increases their size.");
}
return wiktGadgetPrefs__resolve(namespaceKey, preferences);
};
mw.wiktGadgetPrefs = {};
mw.wiktGadgetPrefs.get = wiktGadgetPrefs_get;
// Only to be used by the preferences page.
mw.wiktGadgetPrefs._namespaceToKey = wiktGadgetPrefs__namespace_to_key;
mw.wiktGadgetPrefs._resolve = wiktGadgetPrefs__resolve;
mw.wiktGadgetPrefs._registeredPrefs = wiktGadgetPrefs__registeredPrefs;
})();
// </nowiki>