User:PerfektesChaos/js/preferencesGadgetOptions/d.js

/// User:PerfektesChaos/js/preferencesGadgetOptions/d.js /// 2021-10-08 PerfektesChaos@de.wikipedia // Preferences utilities, gadget options and configuration form // ResourceLoader: compatible; //   dependencies: user.options, mediawiki.user, mediawiki.util /// Fingerprint: #0#0# /// @license GPL [//www.mediawiki.org/w/COPYING] (+GFDL, LGPL, CC-BY-SA) /// /* global window: false, JSON:false                                   */ /* jshint forin:false, bitwise:true, curly:true, eqeqeq:true, latedef:true, laxbreak:true, nocomma:true, strict:true, undef:true, unused:true          */

( function ( mw, $ ) {  "use strict";   var Version    =  -2.1,       Signature  =  "preferencesGadgetOptions",       PREGO      =  { signature: "ext.gadget." + Signature,                       special:   "Blankpage",                       type:      Signature,                       vsn:       Version,                       api:       { },                       cache:     { },                       date:      { },                       dialog:    { },                       hook:      { },                       lang:      { },                       option:    { },                       page:      { } };

/*   * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as   * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. *   * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. *   * You should have received a copy of the GNU General Public License * along with this program; * if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * http://www.gnu.org/copyleft/gpl.html */

// Requires: JavaScript 1.3   (String.charCodeAt String.replace) //          MediaWiki   1.26  (mw.storage, mw.libs, jQuery core)

function fire { // Environment initialized // Precondition: //   user.options and basic resources have been loaded // Postcondition: //   Ready to be used // Uses: //   >  .type //    < .doc //    < .lang.user //    < .local //   mw.user.isAnon //   mw.loader.using //   .hook.fire //   .finalize //   (.cache.first) // Remark: Used as event handler -- 'this' is not PREGO // 2018-05-02 PerfektesChaos@de.wikipedia PREGO.doc       =  "w:en:User:PerfektesChaos/js/" + PREGO.type                          + ""; PREGO.lang.user =  { "als" :  [ "de", "fr" ], "bar" : [ "de" ], "br" :  [ "fr" ], "cel" : [ "fr" ], "dsb" : [ "hsb", "de" ], "fro" : [ "fr" ], "frp" : [ "fr" ], "frr" : [ "de", "nl" ], "fur" : [ "it" ], "fy" :  [ "nl" ], "gsw" : [ "de" ], "hsb" : [ "dsb", "de" ], "ksh" : [ "de" ], "lb" :  [ "de" ], "li" :  [ "nl" ], "lij" : [ "it" ], "lld" : [ "it" ], "lmo" : [ "it" ], "nap" : [ "it" ], "nds" : [ "de", "nl" ], "nn" :  [ "no", "da", "sv" ], "no" :  [ "nn", "da", "sv" ], "oc" :  [ "fr" ], "pdc" : [ "de" ], "pdt" : [ "de" ], "pfl" : [ "de" ], "pms" : [ "it" ], "sc" :  [ "it" ], "sli" : [ "de" ], "stq" : [ "de" ], "vec" : [ "it" ], "vls" : [ "nl" ], "vmf" : [ "de" ], "wa" :  [ "fr" ] //"simple": Universal fallback "en" };  // 2017-11-11 PerfektesChaos@de.wikipedia PREGO.local =  mw.user.isAnon; if ( PREGO.local ) { mw.loader.using( [ "mediawiki.storage" ],                         PREGO.cache.first ); } else { PREGO.finalize; }     PREGO.hook.fire; }  // fire

function first { // Autorun // Uses: //   >  .signature //   >  .type //   >  mw.libs //   >< PREGO //   mw.loader.getState //   mw.loader.state //   mw.loader.using // 2018-08-24 PerfektesChaos@de.wikipedia var launch, prev, rls; if ( mw.loader.getState( PREGO.signature ) !==  "ready" ) { rls = { }; rls[ PREGO.signature ] = "ready"; mw.loader.state( rls ); if ( typeof mw.libs[ PREGO.type ] !==  "object"   ||              !      mw.libs[ PREGO.type ] ) { mw.libs[ PREGO.type ] =  PREGO; launch =  true; } else { prev   =  mw.libs[ PREGO.type ]; launch =  ( typeof prev.vsn  ===  "undefined" ); if ( launch ) { $.extend( prev, PREGO ); PREGO =  prev; }        }         if ( launch ) { mw.loader.using( [ "user",                              "user.options",                               "mediawiki.user" ],                             fire ); }     }   }   // first

PREGO.api.failed =  function ( about, add, aborted ) { // API attempt failed // Precondition: //   about    -- reason //   add      -- object with details //   aborted  -- callback error function (optional), or false // Postcondition: //   message is displayed // Uses: //   mw.hook //   (.api.flop) // Remark: Used as event handler -- 'this' is not PREGO.api // 2013-12-19 PerfektesChaos@de.wikipedia var s =  "API error"; if ( about ) { s =  s + "\n\n" + about; }     if ( add ) { if ( add.error ) { if ( add.error.info ) { s =  s + ":\n" + add.error.info; }        }      }      s  =  s + "\n\n* Login session might have been expired."; if ( typeof aborted ===  "function" ) { aborted.call( PREGO, s ); }     mw.hook( "wikipage.content" ).add( function  {                                                     PREGO.api.flop( s );                                                     } ); };  // .api.failed

PREGO.api.fiat =  function ( api, apply ) { // Store one element in queue as preference // Postcondition: //   api     -- mw.Api object //   apply   -- request details //              [0] preference (without "userjs-") //              [1] value //              [2] callback function (optional) //              [3] error function (optional) //              [4] jQuery object of option/gadget //   mw.user.tokens.get //   (.api.follow) //   (.api.failed) // 2021-10-08 PerfektesChaos@de.wikipedia var pars = { "action":     "options", "token":     mw.user.tokens.get( "csrfToken" ), "optionname": apply[ 0 ] }; if ( apply[ 1 ] !==  null ) { pars.optionvalue =  apply[ 1 ]; }     api.post( pars ) .done( function ( d, t, j ) {                                    PREGO.api.follow( true, apply[ 4 ] );                                    if ( apply[ 2 ] ) {                                        apply[ 2 ].call( null, d, t, j );                                     }                } ) .fail( function ( d, t, j ) {                                    PREGO.api.failed( d );                                     PREGO.api.follow( false, apply[ 4 ] );                                    if ( apply[ 3 ] ) {                                        apply[ 3 ].call( null, d, t, j );                                     }                } ); };  // .api.fiat

PREGO.api.fire =  function ( assign, apply, any, after, aborted, at ) { // Initiate storing an option value on server // Precondition: //   assign    -- string with option/gadget identification //   apply     -- string value, or null for deletion //   any       -- assign is mediawiki option name, or false //   after     -- callback function (optional), or false //   aborted   -- error function (optional), or false //   at        -- issued by gadget dialog form // Postcondition: //   Returns false if valid, else error message on parameter fault // Uses: //   this //   >  .page.$throbber //   >  mw.util.$content //   >< .api.queue //   .page.fragment //   .page.factory //   mw.loader.using //   (.api.forward) // 2021-10-08 PerfektesChaos@de.wikipedia var $api =  false, r, s, task; if ( typeof assign ===  "string" ) { if ( /[^a-zA-Z0-9_-]/.test( assign ) ) { r =  "invalid character in key 'assign'"; } else if ( apply === null                    ||   typeof apply  ===  "string" ) { r =  false; } else { r =  "invalid type for value 'apply'"; }     } else { r =  "key 'assign' not a string"; }     if ( ! r ) { if ( at ) { s    =  "#" + PREGO.page.fragment( assign ); $api =  mw.util.$content.find( s ); if ( $api.length ) { $api.empty; if ( ! PREGO.page.$throbber ) { PREGO.page.factory( "$throbber" ); }              $api.append( PREGO.page.$throbber.clone ); }        }         task  =  [ ( any  ?  assign  :  "userjs-" + assign ), apply, false, false, $api ]; if ( typeof after ===  "function" ) { task[ 2 ] =  after; }        if ( typeof aborted  ===  "function" ) { task[ 3 ] =  aborted; }        if ( this.queue ) { this.queue.push( task ); } else { this.queue =  [ task ]; }        mw.loader.using( [ "mediawiki.api" ],                          this.forward ); }     return r;   };   // .api.fire

PREGO.api.fix =  function ( arrived, assign, advanced, after, assume ) { // Update mw object and notify user by callback // Precondition: //   arrived  -- JSON result of ajax query //   assign   -- string with option identification //   advanced  -- assign is mediawiki option name, or false //                0  -- mediawiki option //                1  -- userjs single value //                2  -- Gadgets //   after    -- callback function (optional) //   assume   -- fallback value, if undefined or failure // Uses: //   mw.user.options.set //   .get //   .fetch // Remark: Used as event handler -- 'this' is not PREGO.api // 2013-09-19 PerfektesChaos@de.wikipedia var q =  arrived.query, s;     if ( q ) { q =  q.userinfo; if ( q ) { q =  q.options; if ( q ) { s =  ( advanced  ?  "userjs-" + assign  :  assign ); q =  q[ s ]; mw.user.options.set( s, q ); if ( typeof after ===  "function" ) { switch ( advanced ) { case 1: q =  PREGO.get( assign, assume ); break; case 2: q =  PREGO.fetch( assign, assume ); break; }  // switch advanced after.call( PREGO, q ); }           }         }      }   };   // .api.fix

PREGO.api.flop =  function ( about ) { // Display error message //   about  -- message // Uses: //   >  .type //   >  mw.util.$content // Remark: Used as event handler -- 'this' is not PREGO.api // 2013-12-29 PerfektesChaos@de.wikipedia var $div  =  $( " " ), $span =  $( " " ); $div.attr( "class", "error" ); $span.text( " " + PREGO.type + " " + about + " " ); $div.append( $span ); mw.util.$content.prepend( $div ); };  // .api.flop

PREGO.api.follow =  function ( achieved, $apply ) { // Confirm success // Precondition: //   achieved  -- true: success //   $apply    -- container for icons // 2015-09-25 PerfektesChaos@de.wikipedia var src; if ( $apply  &&  $apply.length ) { src =  ( achieved ? "$stored" : "$denied" ); $apply.empty; if ( ! PREGO.page[ src ] ) { PREGO.page.factory( src ); }        $apply.append( PREGO.page[ src ].clone ); }  };   // .api.follow

PREGO.api.forward =  function  { // Store all elements in queue as preferences // Uses: //   >  mw.Api //   >< .api.queue //      [0] preference (without "userjs-") //      [1] value //      [2] callback function (optional) //      [3] error function (optional) //   .api.fiat // Remark: Used as event handler -- 'this' is not PREGO.api // 2021-10-08 PerfektesChaos@de.wikipedia var i, n, request; if ( PREGO.api.queue ) { n =  PREGO.api.queue.length; if ( n > 0 ) { request =  new mw.Api; for ( i = 0; i < n;  i++ ) { PREGO.api.fiat( request, PREGO.api.queue[ i ] ); }  // for i         } PREGO.api.queue =  false; }  };   // .api.forward

PREGO.api.fresh =  function ( assign, advanced, assume, after, aborted ) { // Retrieve current option value and update mw object // Precondition: //   assign    -- string with option identification //   advanced  -- assign is mediawiki option name, or false //                0  -- mediawiki option //                1  -- userjs single value //                2  -- Gadgets //   assume    -- fallback value, if undefined or failure //   after     -- callback function, or else //   aborted   -- error callback function (optional), or false // Uses: //   >  mw.Api //   (.api.freshed) //   (.api.failed) // 2013-09-21 PerfektesChaos@de.wikipedia var q =  new mw.Api; q.get( { "action": "query",              "meta":   "userinfo",               "uiprop": "options" } ) .done( function ( arrived ) {              PREGO.api.fix( arrived, assign, advanced, after, assume );                                   } ) .fail( function ( about, add ) {                                PREGO.api.failed( about, add, aborted );                                   } ); };  // .api.fresh

PREGO.cache.first = function  { // Initialize anonymous localStorage // Precondition: //   mediawiki.storage is available // Postcondition: // Uses: //   >  .type //    < .cache.data //   mw.storage.get{} //   JSON.parse //   mw.user.options.set //   .finalize // Remark: Used as event handler -- 'this' is not PREGO.cache // 2016-10-11 PerfektesChaos@de.wikipedia var s =  mw.storage.get( PREGO.type ); if ( s ) { try { PREGO.cache.data =  JSON.parse( s ); } catch(e) { // why ever * corrupted by anyone PREGO.cache.data =  false; }        if ( typeof PREGO.cache.data  ===  "object"              &&     PREGO.cache.data ) { if ( typeof PREGO.cache.data.userjs ===  "object"                 &&     PREGO.cache.data.userjs ) { for ( s in PREGO.cache.data.userjs ) { mw.user.options.set( "userjs-" + s,                                      PREGO.cache.data.userjs[ s ] ); }  // for s in userjs } else { PREGO.cache.data.userjs =  false; }           // other components and preferences might follow } else { PREGO.cache.data =  { }; }     }      PREGO.finalize; };  // .cache.first

PREGO.cache.fill = function ( assign, apply ) { // Store user option with localStorage // Precondition: //   assign  -- string with option/gadget identification //   apply   -- JSONified value // Postcondition: //   Returns boolean on success // Uses: //   this //   >  .cache.data //   >  .type //   >  mw.util.$content //   JSON.stringify //   mw.storage.set //   .page.fragment //   .api.follow // 2015-09-25 PerfektesChaos@de.wikipedia var r =  this.data, s;     if ( r ) { if ( typeof this.data.userjs !==  "object"              ||   ! this.data.userjs ) { this.data.userjs =  { }; }        this.data.userjs[ assign ]  =  apply; r =  mw.storage.set( PREGO.type,                               JSON.stringify( this.data ) ); s =  "#" + PREGO.page.fragment( assign ); PREGO.api.follow( r, mw.util.$content.find( s ) ); }     return r;   };   // .cache.fill

PREGO.cache.free = function ( assign ) { // Store user option with localStorage // Precondition: //   assign  -- string with option/gadget identification //   apply   -- JSONified value // Postcondition: //   Returns boolean on success // Uses: //   this //   >  .cache.data //   >  .type //   JSON.stringify //   mw.storage.set // 2015-09-12 PerfektesChaos@de.wikipedia var r =  this.data; if ( r ) { if ( typeof r.userjs ===  "object"   &&              typeof r.userjs[ assign ]  !==  "undefined" ) { delete this.data.userjs.assign; r =  mw.storage.set( PREGO.type,                                  JSON.stringify( this.data ) ); } else { r =  true; }     } else { r =  false; }     return r;   };   // .cache.free

PREGO.date.format8601 =  function ( age ) { // Format Date object according to ISO8601 // Precondition: //   age  -- Date object (since 1970) // Postcondition: //   Returns string (human readable format) // 2013-09-16 PerfektesChaos@de.wikipedia var jY = age.getUTCFullYear, jM = age.getUTCMonth + 1, jD = age.getUTCDate, kH = age.getUTCHours, kM = age.getUTCMinutes, kS = age.getUTCSeconds, kX = age.getUTCMilliseconds; if ( jM < 10 ) { jM =  "0" + jM; }     if ( jD < 10 ) { jD =  "0" + jD; }     if ( kH < 10 ) { kH =  "0" + kH; }     if ( kM < 10 ) { kM =  "0" + kM; }     if ( kS < 10 ) { kS =  "0" + kS; }     if ( kX < 100 ) { if ( kX < 10 ) { kX =  "00" + kX; } else { kX =  "0" + kX; }     }      return jY + "-" + jM + "-" + jD             + " " + kH + ":" + kM + ":" + kS + "."+ kX            + "Z"; };  // .date.format8601

PREGO.date.from8601 =  function ( age ) { // Retrieve Date object from ISO8601 string (human readable format) // Precondition: //   age  -- string (since 1970) // Postcondition: //   Returns Date object // 2013-09-28 PerfektesChaos@de.wikipedia return new Date( parseInt( age.substr( 0, 4 ),  10 ),                       parseInt( age.substr(  5, 2 ),  10 )   -   1,                       parseInt( age.substr(  8, 2 ),  10 ),                       parseInt( age.substr( 11, 2 ),  10 ),                       parseInt( age.substr( 14, 2 ),  10 ),                       parseInt( age.substr( 17, 2 ),  10 ),                       parseInt( age.substr( 20, 3 ),  10 ) ); };  // .date.from8601

PREGO.dialog.factory =  function ( about ) { // Create form // Precondition: //   about  -- object with gadget description //             >  .$item //             >  .opts //             >  .script //             >  .fiat //              < .selector //              < .$pop //   document.ready // Uses: //   >  .page.$optsForm //   >  .page.$btnClose //   >  .page.$btnSubmit //   >  .page.ltr //   .page.factory //   .option.factory //   .page.fragment //   .page.feature //   (.dialog.forward) // 2019-02-13 PerfektesChaos@de.wikipedia var i, n, $e; if ( typeof about.opts ===  "object"   &&   about.opts ) { n =  about.opts.length; if ( n ) { about.selector =  PREGO.type + "-form_" + about.script; if ( ! PREGO.page.$optsForm ) { PREGO.page.factory( "$optsForm" ); }           about.$pop  =  PREGO.page.$optsForm.clone; about.$pop.attr( "id", about.selector ); if ( ! PREGO.page.$btnClose ) { PREGO.page.factory( "$btnClose" ); }           $e  =  PREGO.page.$btnClose.clone; $e.click( function {   PREGO.dialog.flat( about );                                  } ); about.$pop.append( $e ); for ( i = 0; i < n;  i++ ) { PREGO.option.factory( about.selector,                                    about.opts[ i ],                                     about.$pop ); }  // for i            if ( ! PREGO.page.$btnSubmit ) { PREGO.page.factory( "$btnSubmit" ); }           about.$submit  =  PREGO.page.$btnSubmit.clone; about.$submit.click( function {                                    PREGO.dialog.forward( about );                                 } ); $e =  $( " "); $e.append( about.$submit ); about.$pop.append( $e ); $e =  $( " " ); $e.attr( { "class": PREGO.page.fragment,                       "id":     PREGO.page.fragment( about.script )                     } ); if ( PREGO.page.ltr ) { $e.css( "margin-left", "2em" ); about.$submit.after( $e ); } else { $e.css( "margin-right", "2em" ); about.$submit.before( $e ); }           if ( typeof about.fiat  ===  "function" ) { about.fiat.call( about, about.$submit ); }        } else { $e =  $( " "); $e.attr( "class", "error" ); $e.text( "empty .opts in config" ); about.$pop.append( $e ); }     }      about.$item.append( about.$pop ); };  // .dialog.factory

PREGO.dialog.fetch =  function ( about ) { // Retrieve object with all current values in form // Precondition: //   about  -- object with gadget description // Postcondition: //   Returns all current values as of user.options.userjs // Uses: //   .option.fetch // 2014-02-20 PerfektesChaos@de.wikipedia var i, n, o, v, r;     if ( about.opts ) { r =  { }; n =  about.opts.length; for ( i = 0; i < n;  i++ ) { o =  about.opts[ i ]; v =  undefined; switch ( o.type ) { case "checkbox" : v =  o.$checkbox.prop( "checked" ); break; case "radio" : case "multi" : case "select" : v =  PREGO.option.fetch( o ); break; case "text" : v =  $.trim( o.$text.val ); break; }  // switch .type if ( v !== undefined ) { r[ o.signature ] =  v;            } }  // for i      } else { r =  null; }     return r;   };   // .dialog.fetch

PREGO.dialog.fired =  function ( about ) { // Expand form, create if not yet built // Precondition: //   about  -- object with gadget spec // Uses: //   .dialog.fresh //   .dialog.factory // 2019-02-13 PerfektesChaos@de.wikipedia if ( about.opts  &&   typeof about.opts  ===  "object" ) { PREGO.dialog.fresh( about ); }     if ( about.$pop ) { about.$pop.css( "display", "block" ); } else { PREGO.dialog.factory( about ); }     about.$button.css( "display", "none" ); };  // .dialog.fired

PREGO.dialog.flat =  function ( about ) { // Hide form // Precondition: //   about  -- object with gadget spec // Uses: //   .page.fragment // 2019-02-13 PerfektesChaos@de.wikipedia about.$pop.css( "display", "none" ); about.$button.css( "display", "inline" ); about.$pop.find( "." + PREGO.page.fragment ).empty; };  // .dialog.flat

PREGO.dialog.forward =  function ( about ) { // Perform storage; request API start // Precondition: //   about  -- object with gadget spec // Uses: //   .dialog.fetch //   .forward // 2019-02-13 PerfektesChaos@de.wikipedia var failure, fed, values; values =  PREGO.dialog.fetch( about ); if ( values ) { if ( typeof about.fed ===  "function" ) { fed =  about.fed; } else { fed =  false; }        if ( typeof about.failure  ===  "function" ) { failure =  about.failure; } else { failure =  false; }        PREGO.forward( about.script, values, fed, failure ); if ( typeof about.filled ===  "function" ) { about.filled.call( about, values ); }     }   };   // .dialog.forward

PREGO.dialog.fresh =  function ( about ) { // Preset all option values from user.options // Precondition: //   about  -- object with gadget description // Uses: //   .fetch // 2014-02-20 PerfektesChaos@de.wikipedia var userjs =  PREGO.fetch( about.script ), i, k, n, o, p, v;     if ( userjs ) { n =  about.opts.length; for ( i = 0; i < n;  i++ ) { o =  about.opts[ i ]; v =  userjs[ o.signature ]; if ( v !== undefined ) { switch ( o.type ) { case "checkbox" : case "radio" : case "text" : o.val =  v;                     break; case "multi" : if ( typeof o.poly ===  "object"   &&   o.poly   &&                          typeof v  ===  "object"   &&   v ) { for ( k = 0; k < p.length;  k++ ) { p[ k ].val =  v[ k ]; }  // for k                     } break; }  // switch .type }        }   // for i      } };  // .dialog.fresh

PREGO.dialog.further =  function ( about ) { // Equip item with control for options // Precondition: //   about  -- object with gadget description //             >  .$item //             >  .opts //             >  .script //             >< .$button // Postcondition: //   about.$button has been set and added // Uses: //   >  .page.$btnOpts //   >  .type //   >  window.location.hash //   .page.factory //   .dialog.fired // 2019-02-13 PerfektesChaos@de.wikipedia if ( about.$item &&  about.opts  &&  ! about.$button ) { if ( ! PREGO.page.$btnOpts ) { PREGO.page.factory( "$btnOpts" ); }        about.$button  =  PREGO.page.$btnOpts.clone; about.$button.attr( "id",                            PREGO.type + "-opt_" + about.script ); about.$button.click( function {                                 PREGO.dialog.fired( about );                              } ); if ( window.location.hash ===  "#" + about.script ) { window.location.hash =  ""; this.fired( about ); }        about.$item.append( about.$button ); }  };   // .dialog.further

PREGO.hook.fetch =  function ( assigned, action, assume ) { // Request for a "Gadgets" object stored by .form or .forward // Precondition: //   assigned  -- string with gadget identification //   action    -- callback function //   assume    -- fallback value object, if undefined or failure // Postcondition: //   Fires object, could be null // Uses: //   PREGO.fetch // 2018-05-02 PerfektesChaos@de.wikipedia if ( typeof action ===  "function" ) { action( PREGO.fetch( assigned, assume ) ); }  };   // .hook.fetch

PREGO.hook.fire =  function  { // Start hook listeners // Uses: //   >  .type //   mw.hook //   (.hook.fetch) //   (.form) //   (.forward) //   (.hook.$button) // 2018-05-02 PerfektesChaos@de.wikipedia mw.hook( PREGO.type + ".fetch" ).add( PREGO.hook.fetch ); mw.hook( PREGO.type + ".form" ).add( PREGO.form ); mw.hook( PREGO.type + ".forward" ).add( PREGO.forward ); mw.hook( PREGO.type + ".$button" ).add( PREGO.hook.$button ); };  // .hook.fire

PREGO.hook.$button = function ( action, assign ) { // Request for a [options button] design // Precondition: //   action  -- callback function //   assign  -- optional string with gadget name // Postcondition: //   Fires jQuery object // Uses: //   PREGO.$button // 2018-05-02 PerfektesChaos@de.wikipedia if ( typeof action ===  "function" ) { action( PREGO.$button( assign ) ); }  };   // .hook.$button

PREGO.lang.factory =  function  { // Create translation sequence, if not yet available // Uses: //   this //   >  .lang.user //   >< .lang.polyglott //    < .lang.multi //   mw.config.get //   jQuery.inArray // 2014-02-20 PerfektesChaos@de.wikipedia var i, s, u;     if ( typeof this.polyglott  !==  "object" ) { s =  mw.config.get( "wgUserLanguage" ).toLowerCase; this.polyglott =  [ s ]; if ( s.length > 4 ) {  // Remove RFC 1766 subtag from code if ( s.charCodeAt( 2 ) ===  45 ) {   // '-' this.polyglott.push( s.substr( 0, 2 )  ); }        }         if ( typeof this.user[ s ]  ===  "object" ) { u =  this.user[ s ]; for ( i = 0; i < u.length;  i++ ) { s =  u[ i ]; if ( $.inArray( s, this.polyglott ) <  0 ) { this.polyglott.push( s ); }           }   // for i         } if ( $.inArray( "en", this.polyglott ) <  0 ) { this.polyglott.push( "en" ); }        this.multi  =  this.polyglott.length; }  };   // .lang.factory

PREGO.lang.fetch =  function ( apply ) { // Retrieve string from definition, may be translated // Precondition: //   apply  -- string or object // Postcondition: //   Returns string // Uses: //   this //   >  .lang.multi //   >  .lang.polyglott //   .lang.factory // 2014-02-20 PerfektesChaos@de.wikipedia var r =  "??????????????", i, s;     switch ( typeof apply ) { case "string" : r =  apply; break; case "object" : if ( apply ) { this.factory; for ( i = 0; i < this.multi;  i++ ) { s =  this.polyglott[ i ]; if ( typeof apply[ s ] ===  "string" ) { r =  apply[ s ]; break;  // for i                  } }  // for i            } break; case "undefined" : break; default : r =  apply + ""; }  // switch typeof apply return r;  };   // .lang.fetch

PREGO.option.factory =  function ( assigned, access, $append ) { // Create one option entry in form // Precondition: //   assigned  -- string with gadget selector //   access    -- object with option description //   $append   -- jQuery element to append to      // Uses: //   this //   .option.flag //   .option.faculty //   .option.flipper //   .option.field // 2014-02-20 PerfektesChaos@de.wikipedia var $div, $opt; if ( access.signature ) { access.selector =  assigned + "_" + access.signature; $opt            =  $( " " ); $opt.attr( "id", access.selector ); switch ( access.type ) { case "html" : $opt.append( $( access.source ) ); break; case "checkbox" : this.flag( access, $opt ); break; case "radio" : case "multi" : this.faculty( access, $opt ); break; case "select" : this.flipper( access, $opt ); break; case "text" : this.field( access, $opt ); break; default : $div =  $( " " ); $div.attr( "class", "error" ); $div.text( "Invalid type: " + access.type ); $opt.append( $div ); }  // switch .type $append.append( $opt ); } else { $div =  $( " " ); $div.attr( "class", "error" ); $div.text( "Invalid ID" ); $append.append( $div ); }  };   // .option.factory

PREGO.option.faculty =  function ( access, $append ) { // Create multiple item option control, radio or checkboxes // Precondition: //   access   -- object with option description //   $append  -- jQuery element to append to      // Uses: //   >  .page.ltr //   .lang.fetch // 2018-05-15 PerfektesChaos@de.wikipedia var lone   =  ( access.type === "radio" ), sel    =  access.selector + "_multiple", $div   =  $( " " ), $label =  $( " " ), $sub   =  $( " " ), live, i, k, n, o, v, $group; if ( typeof access.show ===  "undefined" ) { $sub.attr( "class", "error" ); $sub.text( access.selector ); } else { $sub.text( PREGO.lang.fetch( access.show )  ); }     $label.attr( "for", sel ) .append( $sub ); $div.append( $label ); if ( typeof access.poly ===  "object" ) { n =  access.poly.length; if ( n ) { $group =  $( " " ); $group.css( "margin-"                               +  ( PREGO.page.ltr ? "left" : "right" ),                       "3em" ); if ( lone  ||   typeof access.val  ===  "object" ) { v =  access.val; } else { v =  [ access.val ]; }           for ( i = 0;  i < n;  i++ ) { o =  access.poly[ i ]; if ( typeof o ===  "object"  &&  o ) { sel     =  access.selector + "_" + i;                  o.$item  =  $( " " ); o.$item.attr( { type: access.type,                                 id:   sel,                                  name: access.selector } ); if ( lone ) { live =  ( o.val === v ); } else { live =  false; for ( k = 0; k < v.length;  k++ ) { if ( o.val === v[ k ] ) { live =  true; break;  // for k                        } }  // for k                  } if ( live ) { o.$item.prop( "checked", true ); }                 $group.append( o.$item ); $sub =  $( " " ); if ( typeof o.show ===  "undefined" ) { $sub.attr( "class", "error" ) .text( ".poly[" + i + "].show missing" ); } else { $sub.text( PREGO.lang.fetch( o.show )  ); }                 $label  =  $( " " ); $label.attr( "for", sel ) .append( $sub ) .css( "margin-"                               +  ( PREGO.page.ltr ? "left" : "right" ),                             ".5em" ) .append( $( " " ) ); } else { $label =  $( " " ); $label.attr( "class", "error" ) .text( ".poly[" + i + "] is not an object" ); }              $group.append( $label ); }  // for i            $div.append( $group ); } else { $sub =  $( " " ); $sub.attr( "class", "error" ) .text( "empty .poly" ); $div.append( $sub ); }     } else { $sub =  $( " " ); $sub.attr( "class", "error" ) .text( "missing/invalid .poly" ); $div.append( $sub ); }     $append.append( $div ); };  // .option.faculty

PREGO.option.fetch =  function ( access ) { // Retrieve current values in multi-control/multi-value option // Precondition: //   access   -- object with option description // Postcondition: //   Returns single or multi-select value (Array) // Uses: //   >  .type // 2014-02-20 PerfektesChaos@de.wikipedia var i, lone, n, o, swing, r;  //  r  =  undefined if ( typeof access.poly ===  "object" ) { n =  access.poly.length; if ( n ) { switch ( access.type ) { case "radio" : lone =  true;   // fall through case "multi" : swing =  "checked"; break; case "select" : lone  =  access.lone; swing =  "selected"; break; default : mw.log( {loud:true},                         PREGO.type                          + " *** Error .option.fetch " + access.type,                          3,                          access ); }  // switch access.type if ( ! lone ) { r =  [ ]; }           for ( i = 0;  i < n;  i++ ) { o =  access.poly[ i ]; if ( o  &&   typeof o  === "object" ) { if ( o.$item ) { if ( o.$item.prop( swing ) ) { if ( lone ) { r =  o.val; break;  // for i                        } else { r.push( o.val ); }                    }                  }               }            }   // for i         } }     return r;   };   // .option.fetch

PREGO.option.field =  function ( access, $append ) { // Create text field control // Precondition: //   access   -- object with option description //   $append  -- jQuery element to append to      // Uses: //   .lang.fetch //   .page.fiat // 2017-05-15 PerfektesChaos@de.wikipedia var sel    =  access.selector + "_text", $div   =  $( " " ), shift, style, $label, $span; access.$text =  $( " " ); access.$text.addClass( "mw-ui-input" ) .attr( { id:  sel,                           type: "text" } ) .css( { "width": "auto" } ); access.backup =  ( access.val  ?  $.trim( access.val )                                      :  "" ); if ( access.backup ) { access.$text.val( access.backup ); }     if ( ! access.ime ) { access.$text.addClass( "noime" ); }     if ( typeof access.minimum  ===  "number" ) { if ( access.minimum > 0 ) { access.$text.attr( "size", access.minimum ); }     }      if ( typeof access.maxlength  ===  "number" ) { if ( access.maxlength > 0 ) { access.$text.attr( "maxlength", access.maxlength ); }     }      if ( typeof access.field  ===  "function" ) { access.field.call( access, access.$text ); }     if ( typeof access.show  !==  "undefined" ) { $span =  PREGO.page.fiat(  PREGO.lang.fetch( access.show )  ); style =  "margin-"  +  ( PREGO.page.ltr ? "right" : "left" ); shift =  $span.css( style ); if ( typeof shift ===  "string" ) { if ( /^0*[a-z]*$/.test( shift ) ) { shift =  false; }        }         if ( ! shift ) { $span.css( style, "1em" ); }        $label  =  $( " " ); $label.attr( "for", sel ) .append( $span ); $div.append( $label ); }     $div.append( access.$text ); if ( typeof access.suffix !==  "undefined" ) { $span =  PREGO.page.fiat( PREGO.lang.fetch( access.suffix ) ); style =  "margin-"  +  ( PREGO.page.ltr ? "left" : "right" ); shift =  $span.css( style ); if ( typeof shift ===  "string" ) { if ( /^0*[a-z]*$/.test( shift ) ) { shift =  false; }        }         if ( ! shift ) { $span.css( style, "1em" ); }        $label  =  $( " " ); $label.attr( "for", sel ) .append( $span ); $div.append( $label ); }     $append.append( $div ); };  // .option.field

PREGO.option.find =  function ( about, ask ) { // Retrieve option object by identification // Precondition: //   about  -- object with gadget description //   ask    -- string with option identification // Postcondition: //   Returns option object if found, else false // 2013-09-16 PerfektesChaos@de.wikipedia var r =  false, i, n, o;     if ( about.opts ) { n =  about.opts.length; for ( i = 0; i < n;  i++ ) { o =  about.opts[ i ]; if ( o &&  o.script === ask ) { r =  o;               break;   // for i            } }  // for i      } return r;  };   // .option.find

PREGO.option.flag =  function ( access, $append ) { // Create binary checkbox option control // Precondition: //   access   -- object with option description //   $append  -- jQuery element to append to      // Uses: //   >  .page.ltr //   .lang.fetch // 2018-05-15 PerfektesChaos@de.wikipedia var sel    =  access.selector + "_checkbox", $label =  $( " " ); access.$checkbox =  $( " " ); access.$checkbox.attr( { id:  sel,                               type: "checkbox" } ); access.backup =  ( access.val ? true : false ); if ( access.backup ) { access.$checkbox.prop( "checked", true ); }     $append.append( access.$checkbox ); $label.attr( "for", sel ) .css( "margin-" + ( PREGO.page.ltr ? "left" : "right" ),                 ".5em" ); if ( typeof access.show ===  "undefined" ) { $label.text( access.signature ); } else { $label.text( PREGO.lang.fetch( access.show )  ); }     $append.append( $label ); };  // .option.flag

PREGO.option.flipper =  function ( access, $append ) { // Create dropdown selction control, multiple or not // Precondition: //   access   -- object with option description //   $append  -- jQuery element to append to      // Uses: //   >  .page.ltr //   PREGO.lang.fetch // 2017-02-08 PerfektesChaos@de.wikipedia var errs   =  false, sel    =  access.selector + "_poly", $div   =  $( " " ), $label =  $( " " ), $sub   =  $( " " ), live, i, k, n, o, s, v, $select; if ( typeof access.show ===  "undefined" ) { $sub.attr( "class", "error" ) .text( access.selector ); } else { $sub.text( PREGO.lang.fetch( access.show )  ); }     $label.attr( "for", sel ) .append( $sub ); $div.append( $label ); if ( typeof access.poly ===  "object" ) { n =  access.poly.length; if ( n ) { $select =  $( " " ); $select.attr( "id", sel ) .css( "margin-"                               +  ( PREGO.page.ltr ? "left" : "right" ),                        "3em" ); if ( typeof access.max ===  "number"   &&   access.max ) { $select.attr( "size", access.max ); }           if ( access.lone ) { v =  access.val; } else { $select.attr( "multiple", true ); if ( typeof access.val ===  "object" ) { v =  access.val; } else { v =  [ access.val ]; }           }            for ( i = 0;  i < n;  i++ ) { o =  access.poly[ i ]; if ( typeof o ===  "object" ) { o.$item =  $( " " ); if ( access.lone ) { live =  ( o.val === v ); } else { live =  false; for ( k = 0; k < v.length;  k++ ) { if ( o.val === v[ k ] ) { live =  true; break; }                    }   // for k                  } if ( live ) { o.$item.prop( "selected", true ); }                 if ( typeof o.show  ===  "undefined" ) { s =  o.val + ""; } else { s =  PREGO.lang.fetch( o.show ); }                 o.$item.text( s ); $select.append( o.$item ); } else if ( errs ) { errs.push( i ); } else { errs =  [ i ]; }           }   // for i            $div.append( $select ); if ( errs ) { $sub =  $( " " ); $sub.attr( "class", "error" ); n =  errs.length; s =  ".poly["  +  ( n > 1  ?  " "  :  "" ); for ( i = 0; i < n;  i++ ) { if ( i > 1 ) { s =  s + ", "; }                 s  =  s + i;               }   // for i               if ( n === 1 ) { s =  s + "] is not an object"; } else { s =  s + " ] are no objects"; }              $sub.text( s ); $div.append( $sub ); }        } else { $sub =  $( " " ); $sub.attr( "class", "error" ); $sub.text( "empty .poly" ); $div.append( $sub ); }     } else { $sub =  $( " " ); $sub.attr( "class", "error" ); $sub.text( "missing/invalid .poly" ); $div.append( $sub ); }     $append.append( $div ); };  // .option.flipper

PREGO.page.factory =  function ( acquire ) { // Ensure initialization on the fly. Generate GUI elements. // Precondition: //   acquire  -- request //               false           -- general //               "Blankpage" //               "Gadgets" //               "$btnClose", //               "$btnOpts", //               "$btnSubmit"    -- button //               "$optsForm"     -- wrap for any options form // Uses: //   this //   >  .config //   >  .type //   >  Version //   >  mw.util.$content //   >< .page.ltr //   >< .page.gallery //   >< .page.$btnClose //   >< .page.$btnOpts //   >< .page.$btnSubmit //   >< .page.$optsForm //   >< .page.$sectionUser //   >< .page.$throbber //   >< .page.$stored //   >< .page.$denied //   .page.fancy //   mw.config.get // 2018-05-15 PerfektesChaos@de.wikipedia var i, permit, q, s, $e, $v; if ( ! this.gallery ) { this.gallery = { "$btnOpts" : [ "Nuvola_apps_kcmsystem.svg", "7a", true, true ], "$throbber" : [ "Ajax-loader.gif", "de", false, false, "API..." ],           "$stored" :   [ "Symbol_OK.png", "62", true, false, "Okay" ], "$denied" :  [ "Boos.png", "38", true, false, ":-(" ]        };      }      switch ( acquire ) {         case false :            if ( typeof this.ltr  !==  "boolean" ) {               //    PREGO.page.find;  Special:Gadgets only               if ( typeof PREGO.config  ===  "object" &&    PREGO.config ) {                  permit  =  [ "$btnClose",                               "$btnOpts",                               "$btnSubmit",                               "$optsForm",                               "$sectionUser" ];                  for ( i = 0;  i < permit.length;  i++ ) {                     s   =  permit[ i ];                     $e  =  PREGO.config[ s ];                     if ( $e &&  typeof $e  ===  "object" &&  typeof $e.clone  ===  "function" ) {                        this[ s ]  =  PREGO.config[ s ].clone;                     }                  }   // for i               }               this.ltr  =  ( $( window.document ).find( "html" ) .attr( "dir" ) !== "rtl" );            }            break;         case "Blankpage" :            q   =  mw.config.get( "wgFormattedNamespaces" );            $v  =  $( "#firstHeading,#section_0" );            if ( ! $v.length ) {              $v = $( "h1" );            }            $v.eq( 0 ).text( q[ "2" ] + ": " + q[ "2300" ] )                      .attr( "title", Version );            $v  =  mw.util.$content.find( "#mw-content-text" );            $v.empty;            $e  =  $( " " );            $e.attr( { "id":  PREGO.type + "-user" } );            $v.prepend( $e );            this.$sectionUser  =  $e;            $v  =  $( "head" );            $e  =  $v.find( "title" );            $e.remove;            $e  =  $( " " );            $e.text( PREGO.type );            $v.prepend( $e );            break; /* 2016-10 unreachable         case "Gadgets" :            $e  =  $( " " );            $e.attr( "id",  PREGO.type + "-user" )              .css( { "border":  "solid 2px #80FFFF", "margin": "1em", "padding": "1em" } );           $v  =  $( " " );            s   =  mw.config.get( "wgFormattedNamespaces" );            $v.text( s[ "2" ] );            $e.append( $v );            mw.util.$content.append( $e );            this.$sectionUser  =  $e;            break;         case "$btnClose" :         case "$btnOpts" :         case "$btnSubmit" :            if ( ! this[ acquire ] ) {              $e  =  $( " " );               $e.attr( "type", "button" );               switch ( acquire ) {                  case "$btnClose" :                     $e.css( { "background-color": "#FF0000", "color":           "#FFFFFF", "font-size":       "8px", "font-weight":     "bolder", "float":           ( this.ltr ? "right" :                                                                "left" ), "height":          "16px", "padding":         "0", "text-align":      "center", "vertical-align":  "middle", "width":           "16px" } );                    $v  =  $( " " );                     $v.text( "X" );                     break;                  case "$btnOpts" :                     $e.css( { "background-color": "#80FFFF", "margin-bottom":   ".5em" } );                     $e.css( "margin-"  +  ( this.ltr ? "left"                                                      : "right" ), "1em" );                    $e.attr( "title", "Option..." );                    $v  =  this.fancy( acquire, 20 );                     break;                  case "$btnSubmit" :                     $e.css( { "color":       "#00A000", "font-size":  "200%", "font-weight": "bolder", "margin-top": "5px" } );                     $e.attr( "title", "...API...>>" );                     $v  =  $( " " );                     $v.text( "+" );                     break;               }   // switch acquire               $e.append( $v );               this[ acquire ]  =  $e;            }            break;         case "$optsForm" :            if ( ! this.$optsForm ) {              $e  =  $( " " );               $e.attr( "class",  PREGO.type + "-optsForm" )                 .css( { "border":  "solid 1px #80FFFF", "margin": ".5em", "padding": ".5em" } );              this.$optsForm  =  $e;            }            break;         case "$throbber" :         case "$stored" :         case "$denied" :            if ( ! this[ acquire ] ) {              this[ acquire ]  =  this.fancy( acquire, 18 );            }            break;      }   // switch acquire   };   // .page.factory

PREGO.page.fancy =  function ( access, amount ) { // Create thumb image // Precondition: //   access  -- image identifier //   amount  -- number of pixels // Postcondition: //   Returns jQuery object //   this //   >  .page.gallery // 2013-12-26 PerfektesChaos@de.wikipedia var src     =  "//upload.wikimedia.org/wikipedia/commons/", picture =  this.gallery[ access ], s, $r; if ( picture ) { if ( picture[ 2 ] ) { src =  src + "thumb/"; }        s    =  picture[ 1 ]; src =  src  +  s.substr(0, 1)  +  "/"  +  s  +  "/" + picture[ 0 ]; if ( picture[ 2 ] ) { src =  src + "/" + amount + "px-" + picture[ 0 ]; if ( picture[ 3 ] ) { src =  src + ".png"; }        }         $r  =  $( " " ); $r.attr( "src", src ); if ( picture[ 4 ] ) { $r.attr( "alt", picture[ 4 ] ); }     } else { $r =  $( " " ); $r.text( "???" + access + "???" ); }     return $r; };  // .page.fancy

PREGO.page.feature =  function ( about ) { // Create user defined gadget item on page // Precondition: //   about  -- object with gadget description // Postcondition: //   about.$item has been set // Uses: //   this //   >  .page.$sectionUser //   >  .page.$list //   >  .type //   .lang.fetch //   .page.first // 2021-10-08 PerfektesChaos@de.wikipedia var e, i, n, p, say, $a, $span, $span2; if ( typeof this.$sectionUser ===  "undefined" ) { this.first; }     if ( typeof this.$list  ===  "object" ) { if ( typeof about.show ===  "undefined" ) { say =  about.script; } else { say =  PREGO.lang.fetch( about.show ); }        $span   =  $( " " ); $span2 =  $( " " ); $span2.html( say ); if ( typeof about.support ===  "undefined" ) { $span.append( $span2 ); } else { $a =  $( "" ); $a.attr( { href:  PREGO.lang.fetch( about.support ),                       target: "_blank" } ) .append( $span2 ); $span.append( $a ); }        if ( typeof about.suffix  !==  "undefined" ) { $span2 =  $( " " ); $span2.html( PREGO.lang.fetch( about.suffix ) ); $span.append( "&#160;" ); $span.append( $span2 ); }        about.$item  =  $( "" ); about.$item.attr( "id", about.script ); about.$item.append( $span ); say =  say.toLowerCase.replace( /-_.,;/,  " " ); p   =  [ say, about.$item ]; if ( this.gadgets ) { n =  this.gadgets.length; for ( i = 0; i < n;  i++ ) { e =  this.gadgets[ i ]; if ( say <  e[ 0 ] ) { e[ 1 ].before( about.$item ); break;  // for i               } }  // for i            e  =  [ say, about.$item ]; if ( i === n ) { this.$list.append( about.$item ); this.gadgets.push( p ); } else { this.gadgets.splice( i, 0, p ); }        } else { this.$list.append( about.$item ); this.gadgets =  [ p ]; }     } else { about.$item =  true; }  };   // .page.feature

PREGO.page.features =  function  { // Insert one or more gadget items on page // Precondition: //   preferences page // Uses: //   >  .page.queue //   >< .page.launched //   .page.factory //   .page.feature //   .dialog.further // Remark: Used as event handler -- 'this' is not PREGO.page // 2019-02-13 PerfektesChaos@de.wikipedia var gadget, i, n;     if ( ! PREGO.page.launched ) { PREGO.page.launched =  true; PREGO.page.factory( false ); }     n  =  PREGO.page.queue.length; for ( i = 0; i < n;  i++ ) { gadget =  PREGO.page.queue[ i ]; if ( gadget  &&   typeof gadget  ===  "object" ) { if ( typeof gadget.script ===  "string" ) { PREGO.page.queue[ i ] =  gadget.script; } else { PREGO.page.queue[ i ] =  i;            } if ( typeof gadget.$item !==  "object" ) { PREGO.page.feature( gadget ); if ( gadget.$item  &&   gadget.$item !== true                    &&     gadget.opts   &&                    typeof gadget.opts  ===  "object" ) { PREGO.dialog.further( gadget ); }           }         }      }   // for i   };   // .page.features

PREGO.page.fiat =  function ( adjust ) { // Create text field control // Precondition: //   adjust  -- string with possible HTML // Postcondition: //   Returns jQuery object // 2013-10-06 PerfektesChaos@de.wikipedia var $r; if ( adjust.charCodeAt(0) === 60 ) {  // '<' $r =  $( adjust ); } else { $r =  $( " " ); $r.text( adjust ); }     return $r; };  // .page.fiat

/* 2016-10 unreachable page PREGO.page.find =  function  { // Initialize "Gadgets" page server definition items // Precondition: //   "Gadgets" page ready // Uses: //   this //   >  mw.util.$content //    < .page.items // 2016-10-08 PerfektesChaos@de.wikipedia var $items =  mw.util.$content.find( "li" ), n      =  $items.length, i, k, s, $li, $links; this.items =  { }; for ( i = 0; i < n;  i++ ) { $li    =  $items.eq( i ); $links =  $li.find( "a" ); for ( k = 0; k < $links.length;  k++ ) { s =  $links.eq( k ).attr( "title" ); if ( s ) { if ( s.indexOf( "MediaWiki:Gadget-" ) === 0 ) { this.items[ s.substr( 17 ) ] =  $li; break;  // for k               } }        }   // for k      }   // for i   };   // .page.find

PREGO.page.first =  function  { // Initialize page and page section // Precondition: //   Special page ready // Uses: //   this //   >  .special //   >  .page.$sectionUser //   >  .type //   <  .page.$list //   .page.factory // 2016-10-08 PerfektesChaos@de.wikipedia this.factory( PREGO.special ); if ( typeof this.$sectionUser ===  "object" ) { this.$list =  $( " " ); this.$list.attr( "id", PREGO.type + "-list" ); this.$sectionUser.append( this.$list ); }  };   // .page.first

PREGO.page.fragment =  function ( assign ) { // Create identifier for gadget storage submission buttons // Precondition: //   assign  -- string of particular gadget, or nothing // Postcondition: //   Returns string with identifier // Uses: //   >  .type // 2015-09-25 PerfektesChaos@de.wikipedia var r =  PREGO.type + "-SUBMIT"; if ( assign ) { r =  r + "_" + assign; }     return r;   };   // .page.fragment

PREGO.factory =  function ( apply, adjacent ) { // Encode/decode any value // Precondition: //   apply     -- value, of any type;  or encoded string //   adjacent  -- value type for storing, false for retrieving // Postcondition: //   Returns string for storing, or retrieved value // Uses: //   parseInt //   JSON.stringify //   .date.format8601 //   .date.from8601 //   JSON.parse // 2014-10-01 PerfektesChaos@de.wikipedia var r;     if ( adjacent ) {    // storing r =  adjacent + "|"; switch ( r ) { case "boolean|" : if ( apply ) { r =  "boolean|true"; }              break; case "Boolean|" : if ( apply.valueOf ) { r =  "boolean|true"; }              break; case "number|" : case "Number|" : case "string|" : case "String|" : r =  r.toLowerCase + apply; break; case "object|" : if ( r ) { r =  r  +  JSON.stringify( apply ); } else { r =  "null|"; }              break; case "date|" : case "Date|" : r =  "date|" + PREGO.date.format8601( apply ); break; default : r =  "undefined|"; }  // switch typeof apply } else if ( typeof apply ===  "string" ) {    // retrieving r =  apply.indexOf( "|" ); if ( r > 0 ) { switch ( apply.substr( 0, r ) ) { case "boolean" : r =  ( apply === "boolean|true" ); break; case "number" : r =  parseInt( apply.substr( r + 1 ),  10 ); break; case "string" : r =  apply.substr( r + 1 ); break; case "null" : r =  null; break; case "object" : r =  JSON.parse( apply.substr( r + 1 ) ); break; case "date" : r =  PREGO.date.from8601( apply.substr( r + 1 ) ); break; case "undefined" : r =  undefined; break; default : r =  apply; }  // switch typeID } else { r =  apply; }     } else { r =  undefined; }     return r;   };   // .factory

PREGO.fetch =  function ( assign, assume, again, aborted ) { // Retrieve a "Gadgets" object stored by .form or .forward // Precondition: //   assign   -- string with gadget identification //   assume   -- fallback value object, if undefined or failure //               kept unchanged; also default for single values //   again    -- update value from server (optional) //               callback function, or true //   aborted  -- error callback function (optional), or false // Postcondition: //   Returns object, could be null // Uses: //   this //   >  .local //   .api.fresh //   mw.user.options.get //   JSON.parse // 2015-09-12 PerfektesChaos@de.wikipedia var o, r, s;     if ( typeof assign  ===  "string" ) { if ( again &&  ! this.local ) { this.api.fresh( assign, 2, assume, again, aborted ); }        r  =  mw.user.options.get( "userjs-" + assign ); if ( r ) { if ( typeof r ===  "string" ) { o =  JSON.parse( r ); if ( assume  &&   typeof assume  ===  "object" )  { r =  { }; for ( s in assume ) { r[ s ] =  assume[ s ]; }   // for s in assume for ( s in o ) { r[ s ] =  o[ s ]; }   // for s in o               } else { r =  o;               } }        } else if ( r === undefined )  { r =  ( assume ? assume : null ); }     } else { r =  ( assume ? assume : null ); }     return r;   };   // .fetch

PREGO.finalize =  function  { // Ready for use, communicate // Uses: //   this //   >  .type //   mw.hook // 2016-03-18 PerfektesChaos@de.wikipedia mw.hook( this.type + ".ready" ).fire( this ); };  // .finalize

PREGO.form =  function ( about ) { // Show gadget (entry, and dialog) on "Gadgets" page // Precondition: //   about  -- object with gadget description, or false // Postcondition: //   Returns false if valid, else error message on parameter fault // Uses: //   >  .special //   >  .type //   >< .page.queue //   >< .page.launched //   mw.config.get //   .page.features //   mw.loader.load //   mw.hook //   (.page.features) // 2019-02-13 PerfektesChaos@de.wikipedia var r =  false, s =  mw.config.get( "wgCanonicalSpecialPageName" ); if ( s === PREGO.special ) { if ( s === "Blankpage" ) { s =  mw.config.get( "wgTitle" ); r =  ( s.indexOf( "/" + PREGO.type,  3 )   >   0 ); }        if ( r   &&   typeof about  ===  "object" ) { if ( typeof PREGO.page.queue ===  "object" ) { PREGO.page.queue.push( about ); if ( PREGO.page.launched ) { PREGO.page.features; }           } else { PREGO.page.queue    =  [ about ]; PREGO.page.launched =  false; mw.loader.load( [ "mediawiki.ui.input" ] ); mw.hook( "wikipage.content" ).add( PREGO.page.features ); }        }      }      return r;   };   // .form

PREGO.forward =  function ( assign, apply, after, aborted ) { // Store a "Gadgets" options object // Precondition: //   assign   -- string with gadget identification //   apply    -- options object (not null) //   after    -- callback function (optional), or false //   aborted  -- error callback function (optional), or false // Postcondition: //   Returns false if valid, else error message on parameter fault // Uses: //   >  .local //   JSON.stringify //   .cache.fill //   .api.fire //   mw.user.options.set // 2018-05-05 PerfektesChaos@de.wikipedia var r, store; if ( typeof assign ===  "string"   &&           typeof apply  ===  "object"   &&   apply ) { store = JSON.stringify( apply ); if ( PREGO.local ) { PREGO.cache.fill( assign, store ); } else { PREGO.api.fire( assign,                          store,                           false,                           after,                           aborted,                           true ); }        mw.user.options.set( "userjs-" + assign,  store ); r =  false; } else { r =  "ERROR * mw.libs." + PREGO.type + ".forward" + " * invalid arg"; }     return r;   };   // .forward

PREGO.get =  function ( assign, assume, again, aborted ) { // Retrieve a typesafe USERJS option value stored by .put // Precondition: //   assign   -- string with option identification //   assume   -- fallback value, if undefined or failure //   again    -- update value from server //               callback function, or true //   aborted  -- error callback function (optional), or false // Postcondition: //   Returns value, of any type // Uses: //   this //   >  .local //   mw.user.options.get //   .api.fresh //   .factory // 2015-09-12 PerfektesChaos@de.wikipedia var r;     if ( typeof assign  ===  "string" ) { r =  mw.user.options.get( "userjs-" + assign ); if ( this.local ) { if ( typeof r !==  "string" ) { r =  undefined; }        } else if ( again ) { this.api.fresh( assign, 1, assume, again, aborted ); }        if ( r ) { r =  this.factory( r,  false ); }     }      if ( r === undefined ) { r =  assume; }     return r;   };   // .get

PREGO.put =  function ( assign, apply, after, aborted ) { // Store a typesafe USERJS option value // Precondition: //   assign   -- string with option identification //   apply    -- value, of any type //   after    -- callback function (optional), or false //   aborted  -- error callback function (optional), or false // Postcondition: //   Returns false if valid, else error message on parameter fault // Uses: //   this //   >  .local //   .factory //   .cache.fill //   .api.fire //   mw.user.options.set // 2015-09-12 PerfektesChaos@de.wikipedia var s = $.type( apply ), r;     if ( ! apply  &&  s === "object" ) { s =  "null"; }     s  =  this.factory( apply, s ); if ( this.local ) { this.cache.fill( assign, s ); r =  false; } else { r =  this.api.fire( assign, s, false, after, aborted ); if ( r &&  s === "object" ) { r =  false; }     }      mw.user.options.set( "userjs-" + assign,  s ); return r;  };   // .put

PREGO.remove =  function ( assign, after, aborted ) { // Remove a preference entry // Precondition: //   assign   -- string with option identification //   after    -- callback function (optional), or false //   aborted  -- error callback function (optional), or false // Postcondition: //   Returns false if valid, else error message on parameter fault // Uses: //   this //   >  .local //   .api.fire //   mw.user.options.get //   mw.user.options.set // 2015-09-12 PerfektesChaos@de.wikipedia var r, s, v;     if ( this.local ) { this.cache.free( assign ); } else { r =  this.api.fire( assign, null, false, after, aborted ); }     if ( ! r ) { s =  "userjs-" + assign; v =  mw.user.options.get( s ); if ( v !== null &&  v !== undefined ) { mw.user.options.set( s, null ); }     }      return r;   };   // .remove

PREGO.string =  function ( assign, apply, after, aborted ) { // Store a string value of a MEDIAWIKI preference //   Note that "false" causes other behaviour than false. // Precondition: //   assign   -- string with option name //   apply    -- string value //   after    -- callback function (optional), or false //   aborted  -- error callback function (optional), or false // Postcondition: //   Returns false if valid, else error message on parameter fault // Uses: //   this //   >  .type //   .api.fire //   mw.user.options.set // 2013-09-19 PerfektesChaos@de.wikipedia var r;     if ( typeof assign  ===  "string"   &&           typeof apply  ===  "string" ) { r =  this.api.fire( assign, apply, true, after, aborted ); mw.user.options.set( assign, apply ); } else { r =  "ERROR * mw.libs." + PREGO.type + ".string" + " * invalid arg"; }     return r;   };   // .string

PREGO.translation =  function ( available ) { // Retrieve best translation from object // Precondition: //   available   -- object with items accessible by language code // Postcondition: //   Returns component with best matching language code // Uses: //   this //   >  .lang.polyglott //   >  .lang.multi //   .lang.factory // 2014-03-20 PerfektesChaos@de.wikipedia var r =  false, i, slang; if ( typeof this.lang.polyglott !==  "object" ) { this.lang.factory; }     if ( typeof available  ===  "object"   &&           available ) { for ( i = 0; i < this.lang.multi;  i++ ) { slang =  this.lang.polyglott[ i ]; if ( typeof available[ slang ] !==  "undefined" ) { r =  available[ slang ]; break;  // for i            } }  // for i      } return r;  };   // .translation

PREGO.translator =  function  { // Retrieve Array with possible language codes // Postcondition: //   Returns Array with possible language codes, sorted best first // Uses: //   this //   >  .lang.polyglott //   .lang.factory // 2014-03-19 PerfektesChaos@de.wikipedia if ( typeof this.lang.polyglott !==  "object" ) { this.lang.factory; }     return this.lang.polyglott; };  // .translator

PREGO.update =  function ( assign, after, aborted ) { // Update the value of a MEDIAWIKI preference // Precondition: //   assign   -- string with option name //   after    -- callback function after update //   aborted  -- error callback function (optional), or false // Postcondition: //   Returns false if valid, else error message on parameter fault // Uses: //   this //   >  .type //   mw.user.options.get //   .api.fresh // 2013-09-28 PerfektesChaos@de.wikipedia var r;     if ( typeof assign  ===  "string" ) { this.api.fresh( assign,                        0,                         mw.user.options.get( assign ),                         after,                         aborted ); r =  false; } else { r =  "ERROR * mw.libs." + PREGO.type + ".update" + " * invalid arg"; }     return r;   };   // .update

PREGO.$button =  function ( assign ) { // Retrieve current [options button] design // Precondition: //   assign   -- optional string with gadget name // Postcondition: //   Returns jQuery object // Uses: //   >  .special //   >  .type //   >  .page.$btnOpts //   mw.config.get //   mw.util.getUrl //   .page.factory // 2016-10-09 PerfektesChaos@de.wikipedia var shift   =  mw.config.get( "wgDBname" ) + "Gadgets", special =  ( PREGO.special === "Blankpage"  ?                        "Blankpage/" + PREGO.type      :                        PREGO.special ), src     =  window.location.protocol + "//" + window.location.host + mw.util.getUrl( "Special:" + special ), $btn; if ( assign ) { src =  src + "#" + assign; }     if ( ! PREGO.page.$btnOpts ) { PREGO.page.factory( "$btnOpts" ); }     $btn  =  PREGO.page.$btnOpts.clone; $btn.click( function {                     window.open( src, shift );                     // Returns always false, stop the bubbling                     return false;                  } ); return $btn; };  // .$button

first; }( window.mediaWiki, window.jQuery ) );

// Emacs // Local Variables: // coding: utf-8-dos // fill-column: 80 // End:

/// EOF  preferencesGadgetOptions/d.js