User:PerfektesChaos/js/preferencesGadgetOptions
Library with JavaScript functions to support configurable gadgets.
Core issue is an interactive dialog form easy to create on Special:Blankpage. Utilities are also manipulating the MediaWiki user preferences. Gadget options are available for anonymous users, too.
Features
editStoring of information is done via API on MediaWiki server.
For retrieving the options set of the current page is evaluated, which has been transferred recently. However, an option might have been changed on a different page in another browser window.
Gadget configuration by GUI
editFrom the form information a GUI is built on Special:Blankpage on the fly. If confirmed by + the last desires of the user will be stored as preferences and may be retrieved on any other page.
Project wide defined tools listed on MediaWiki:Gadgets-definition appear on Special:Blankpage anyway. If a configuration dialog has been defined and the user selected this particular tool, a button is added to the existing entry.
User scripts which are not registered as project gadgets get their own section on top of the special page.
Even if no configuration is supported, a link to documentation page may be displayed, and correct installation and presence is confirmd by visible entry.
Type safe user JS
editThe MediaWiki supports only string values. Since "false"
shows very different behaviour on control structures than false
(and "null"
is not null
nor is "5"+7
the same as 5+7
) single values are returned as stored.
Entire option sets of a gadget are stored by JSON which keeps type.
Preferences
editSome utility functions support common MediaWiki user preferences:
Only strings may be assigned as MediaWiki standard preferences, and the value has to be valid as if entered on Special:Preferences.
Updating
editIt is possible to update a particular option within the current page. The page might have been delivered some time ago, while the value has been changed within another browser window.
Callback
editIf wiki server needs to be contacted, the return values of functions are not the ultimate responses. If an updated value is to be retrieved from server, it will arrive with some delay on a callback function. Notification about successful storage may be requested as well as alerting on exchange errors.
User defined preferences storing
editCurrently the following component range is used for storing of preferences other than from MediaWiki extensions:
mw.user.options.values.userjs-
gadgetID
This might change one day, perhaps
mw.user.config.values.
gadgetID
The script maintains independent access to this storage, even automatic migration.
Data consumption
edit- Every time a user is requesting a page (after login), the entire set of options is transferred from server. No caching on local browser storage is done.
- For better management and faster network communication there is only one object with the entire option set for each gadget.
- This is much more efficient than a gadget identifier combine with a single option name for each value.
- It also enables easy combination with an entire set of default values modified by user preferences.
- The amount of data which needs to be transferred every time should be kept small. Persistent configuration information should be put into specific configuration script pages hold by browser cache, or put into localStorage/sessionStorage (Web Storage) after first access.
Anonymous users
editWhile preferences and gadget options are stored on a wiki server if login performed, anonymous users may recall gadget options at least within the same browser profile.
The web storage feature, which is available on all recent major browsers will save information between pages and sessions.
Anonymous users may use greasemonkey to trigger any script.
Gadget maintainers need not to know whether options have been saved on server or locally.
Installation
editGadget programmers need to wait for correct installation of this script before any function can be used.
If the gadget decided that the library is needed, the following code will load the source if not yet present.
if ( ! mw.loader.getState( "ext.gadget.preferencesGadgetOptions" ) ) {
mw.loader.state( { "ext.gadget.preferencesGadgetOptions": "loading" } );
mw.loader.load( "https://en.wikipedia.org/w/index.php?title="
+ "User:PerfektesChaos/js/"
+ "preferencesGadgetOptions/r.js"
+ "&action=raw&bcache=1&maxage=604800"
+ "&ctype=text/javascript" );
}
mw.hook( "preferencesGadgetOptions.ready" ).add( callback );
The state of this script is checked first to avoid repeated loading. Another gadget which also uses this script library might be loading already. Therefore the state is set to "loading"
immediately.
A callback function will be executed as soon as loading has been completed, or right now, if already available. All functionality relying on the library is to be accessed within the callback function. The callback function will receive the library object as first parameter.
API
editAfter the mw.hook
preferencesGadgetOptions.ready
has been triggered functions may be called. The application object is the parameter of the mw.hook callback function and should be identical with mw.libs.preferencesGadgetOptions
.
All functions are components of the application object.
function | scope | purpose | ||
---|---|---|---|---|
Gadgets | UserJS | MediaWiki | ||
.fetch()
|
× | – | – | Retrieve option set |
.form()
|
Dialog form on Special:Blankpage | |||
.forward()
|
Store option set | |||
.$button()
|
Retrieve jQuery button opening special page | |||
.get()
|
– | × | – | Retrieve typesafe single userjs option |
.put()
|
Store typesafe single userjs option | |||
.remove()
|
× | × | × | Remove user option from preferences |
.string()
|
– | – | × | Store MediaWiki preference string |
.update()
|
Update the value of a MediaWiki preference |
.fetch()
editRetrieve a “Gadgets” option set stored by .form()
or .forward()
.
Call | .fetch(assign, assume, again, aborted)
| ||
---|---|---|---|
Parameter | Type | Meaning | |
assign
|
string
|
gadget identification | |
assume
|
object
|
| |
again
|
function boolean
|
update value from server
| |
aborted
|
function
|
attempt to update again failed
| |
Return value | object as of current page state and assume ; could be null
|
This functionality is also available as hook.
.form()
editShow gadget (entry, and dialog) on Special:Blankpage. If already registered by project, only append button to open form, if any.
Call | .form(about)
| ||
---|---|---|---|
Parameter | Type | Meaning | |
about
|
object
|
gadget description, see below |
This functionality is also available as hook.
.forward()
editStore a "Gadgets" options object.
Call | .forward(assign, apply, after, aborted)
| ||
---|---|---|---|
Parameter | Type | Meaning | |
assign
|
string
|
gadget identification | |
apply
|
object
|
key:value assignments as needed | |
after
|
function boolean
|
storing succeeded
| |
aborted
|
function
|
storing failed
| |
Return value | false if valid, else error message on parameter fault
|
This functionality is also available as hook.
.$button()
editRetrieve a jQuery button in current design, opening the Special:Blankpage.
Call | .button(assign)
| ||
---|---|---|---|
Parameter | Type | Meaning | |
assign
|
string optional |
gadget identification; opens specified options form on Special:Blankpage. | |
Return value | jQuery button |
This functionality is also available as hook.
.get()
editRetrieve a typesafe USERJS option value stored by .put().
Call | .get(assign, assume, again, abort)
| ||
---|---|---|---|
Parameter | Type | Meaning | |
assign
|
string
|
gadget identification | |
assume
|
any optional |
fallback value if not retrieved or missing | |
again
|
function boolean
|
update value from server
| |
aborted
|
function
|
attempt to update again failed
| |
Return value | value, of any type; at least assume
|
.put()
editStore a typesafe USERJS option value. Supposed to be retrieved by .get().
Call | .put(assign, apply, after, aborted)
| ||
---|---|---|---|
Parameter | Type | Meaning | |
assign
|
string
|
gadget identification | |
apply
|
any | value to be stored. | |
after
|
function
|
storing succeeded
| |
aborted
|
function
|
storing failed
| |
Return value | false if valid, else error message on parameter fault
|
.remove()
editRemove a user option entry from preferences.
Call | .remove(assign, after, aborted)
| ||
---|---|---|---|
Parameter | Type | Meaning | |
assign
|
string
|
option identification | |
after
|
function
|
deletion performed
| |
aborted
|
function
|
deletion failed
| |
Return value | false if valid, else error message on parameter fault
|
.string()
editStore a string value of a MEDIAWIKI option.
Call | .string(assign, apply, after, aborted)
| ||
---|---|---|---|
Parameter | Type | Meaning | |
assign
|
string
|
MediaWiki option name | |
apply
|
string
|
value | |
after
|
function
|
storing succeeded
| |
aborted
|
function
|
storing failed
| |
Return value | false if valid, else error message on parameter fault
|
.update()
editUpdate the value of a MEDIAWIKI option.
Call | .update(assign, after, aborted)
| ||
---|---|---|---|
Parameter | Type | Meaning | |
assign
|
string
|
MediaWiki option name | |
after
|
function
|
updating successfully finished
| |
aborted
|
function
|
updating failed
| |
Return value | false if valid, else error message on parameter fault
|
GUI for Special:Blankpage
editUser and project defined gadgets may be advertised and configured on Special:Blankpage page.
- If already defined by MediaWiki:Gadgets-definition and chosen by user, only append button to open form, if any.
- If user script has not been registered as project gadget a particular section will be inserted on top of the special page. Every unregistered user script gets an entry and may link to its documentation page.
If the about.opts
is specified a button is appended to open a dialog form, which may be closed again later.
- The form provides a submit button + that launches a page and server update if clicked.
From the following components all but .script
are optional; but some more than the gadget ID only make look the GUI pretty and functional.
Component | Type | Meaning |
---|---|---|
.script
|
string
|
mandatory gadget ID |
.suite
|
string
|
ID in MediaWiki:Gadgets-definition
|
.show
|
string
|
displayed name of gadget
|
.support
|
string
|
URL of gadget documentation page "/wiki/User:PerfektesChaos/js/preferencesGadgetOptions" |
.suffix
|
string
|
further explanation of the gadget (an opt-in user should already know) Is appended to the name |
.fiat
|
function
|
function called after .opts equipped the form.In |
.filled
|
function
|
function called after submit button + has been pressed. The function receives as first parameter the object |
.fed
|
function
|
callback function executed after successful storing on server |
.failure
|
function
|
callback function executed if storing on server failed |
.opts
|
Array
|
configurable options
|
Component | Type | Meaning |
---|---|---|
.signature
|
string
|
mandatory option ID |
.type
|
string
|
mandatory option type; one of
|
.show
|
string
|
option description |
.val
|
any | default setting, and current choice |
.poly
|
Array
|
multiple control definition (.type=radio|multi only).Every Array element is an
For |
.suffix
|
string
|
.type=text only (optional)description appended to text input field may be wrapped as HTML element. |
.minimum
|
string
|
.type=text only (optional)displayed length (guessed) of input field in characters |
.maxlength
|
number
|
.type=text only (optional)maximum permitted length of input string in characters |
.ime
|
boolean
|
.type=text only (optional)
|
.field
|
function
|
.type=text only (optional)Function receiving the jQuery object of input field as parameter. |
.$checkbox .$item .$text
|
object
|
jQuery object generated by the script after first opening of the form |
Callback function
editIf desired a user defined function is called as soon as an action on Wiki server has been completed. These functions share the following specification:
- Called with one parameter:
- For a function of successful execution this is the current option value.
- For a function in case of failure it is a string with best error description available.
this
is the application objectmw.libs.preferencesGadgetOptions
.
Synchronisation
editFor vulnerable operations it might be crucial that configuration has not been changed within another window since the page has been displayed. By the updating function and callback functions it can be ensured that operations are not executed before the most recent state was taken into account.
Waiting for availability
editIt might happen that this library is unavailable or could crash due to syntax error or other situation.
- The success function of
.using()
should check first availability of the object componentmw.libs.preferencesGadgetOptions
and the desired function components. If those are missing it needs to be continued with standard values without supporting specific user options. - This might be logged on console to help quick remediation.
Configuration of special page
editFor the entire project the default rearrangement of Special:Blankpage might be influenced by project administration, in particular by MediaWiki:Common.js which is executed in advance.
Change of project configuration by gadgets is not desired and might be treated by sysops as misuse.
Instead of default styles jQuery objects will be used if present. The following code could be completed to provide project specific design:
if ( mw.config.get( "wgCanonicalSpecialPageName" ) === "Blankpage" ) {
mw.libs.preferencesGadgetOptions.config = {
$btnOpts: $( ... ),
$sectionUser: $( ... ),
...
};
}
jQuery objects | |
---|---|
.$sectionUser
|
Wrapper object for the section on user defined scripts.<div id="preferencesGadgetOptions-user"> Includes:
One |
.$optsForm
|
<div class="preferencesGadgetOptions-optsForm"> for any single option form.
|
.$btnOpts
|
<button> control for opening an option form.
|
.$btnSubmit
|
<button> control for transmission of the options set.
|
.$btnClose
|
<button> control for closing an option form.
|
.$throbber
|
<img> for API in progress.
|
.$stored
|
<img> for successful storing on server.
|
.$denied
|
<img> for API failure.
|
The default design may be taken from the following CSS:
div.preferencesGadgetOptions-optsForm {
border: solid 1px #80FFFF;
margin: .5em;
padding: .5em;
}
div#preferencesGadgetOptions-user {
border: solid 2px #80FFFF;
margin: 1em;
padding: 1em;
}
Hooks
editThe following identifiers are registered utilizing mw.hook()
system:
- Fired:
preferencesGadgetOptions.ready
when library has been provided and initialized, and user options are available. The parameter is the application library.
- Listening:
preferencesGadgetOptions.fetch
Request for aGadgets
object stored by.form()
or.forward()
; parameters:assigned
– string with gadget identificationaction
– callback function, retrieves.fetch()
result when availableassume
– optional fallback value object, if undefined or failure
preferencesGadgetOptions.form
Like.form()
; parameters:about
– object with gadget description
preferencesGadgetOptions.forward
Like.forward()
; parameters:assign
– string with gadget identificationapply
– options object (not null)after
– optional callback function, or falseaborted
– optional callback function, or false
preferencesGadgetOptions.$button
Request for a [options button] design; parameters:action
– callback function, retrieves jQuery button when availableassign
– optional string with gadget name
Hook listeners give the opportunity to fire and forget requests, with no need to wait until library has loaded.
Codes
editSource code |
|
ResourceLoader |
|
Namespaces |
|
Cookies | Anonymous users only:
|
mw.libs
|
preferencesGadgetOptions
|
mw.hook
|
preferencesGadgetOptions.ready Fired when library has been provided and initialized, and user options are available.
|
MediaWiki |
|
Known applications
editOther languages
editThis gadget would be prepared for multilingual support but does not need any.
- All language dependent strings are provided by the application if correctly used.
- RTL of entire page is automatically taken into account for element arrangement.
- If the application is not configured well red error messages in English might appear. These should be fixed by the programmer first.
Translations of this documentation are welcome.