Wikipedia:Dateiwartung/Werkzeug/d.js

aus Wikipedia, der freien Enzyklopädie
Zur Navigation springen Zur Suche springen

///

<nowiki>             f i l e A d m
// Unterstützungswerkzeug für Dateien, Dateikategorien, DÜP, Dateirechte.
/// 2014-06-05 PerfektesChaos@de.wikipedia
/// Fingerprint:   #0#0#
//  ResourceLoader:  compatible;
//     dependencies: user,
//                   mediawiki.api, mediawiki.user, mediawiki.util
//     namespaces:   -1, 4, 6, 14, 100
//  Documentation:   Wikipedia:Dateiwartung/Werkzeug
/*jshint curly:true, latedef:true, laxbreak:true,
         strict:true, trailing:true, undef:true, white:false           */
/*global window: true, document: true, mediaWiki: false, jQuery: true,
         unescape: true                                                */
/*jslint  browser: true, plusplus: true, regexp: true, unparam: true,
          vars: true, white: true, maxerr: 50                          */
/*globals jQuery: true, mediaWiki: false, unescape: true               */

( function ( mw ) {
   "use strict";
   var FAdm,
       vsn   =  -1.001;
   if ( typeof( mw.libs.fileAdm )  !==  "object" ) {
      mw.libs.fileAdm  =  { };
   }
   FAdm       =  mw.libs.fileAdm;
   FAdm.doc   =  "[[w:de:Wikipedia:Dateiwartung/Werkzeug]]";
   FAdm.obj   =  "mw.libs";
   FAdm.type  =  "fileAdm";
   FAdm.vsn   =  vsn;
   // Uses:
   //    MediaWiki 1.18
   //              mw.libs
   //              mw.user.tokens
   //              mw.util
   //                 .addCSS
   //                 .addPortletLink
   //                 .getParamValue
   //                 .wikiGetlink
   //                 .wikiScript
   //                 .wikiUrlencode
   //    jQuery
   //       Beyond basics:
   //       .ajaxError()
   //       .cookie()
   //       .get()
   //       .getJSON()
   //       .post()
   //       .ready()
   //    JavaScript 1.5



   if ( typeof( FAdm.bb )  !==  "object" ) {
      FAdm.bb  =  { };
   }
   //   .all       overall structure and data
   //   .batch     API.php
   //   .cat       categories containing files
   //   .edit      editing page content
   //   .file      file description page
   //   .guide     special view on some pages
   //   .hover     unused
   //   .ia        interactive editing
   //   .key       Info template
   //   .misc      utilities and anything
   //   .ns        namespaces
   //   .opt       forms and user config
   //   .portlet   page portlet
   //   .queer     file checking
   //   .review    file review
   //   .str       general string repository
   //   .trans     file transfer to commons
   //   .users     special user groups
   //   .wins      browser windows
}( mediaWiki ) );



//-----------------------------------------------------------------------



mediaWiki.libs.fileAdm.bb.debugging  =  function ( FAdm ) {
   // Development support
   // 2012-06-12 PerfektesChaos@de.wikipedia
   "use strict";
   if ( typeof FAdm.debugging !== "object" ) {
      FAdm.debugging  =  { loud: false  };   // not a developer
   }



   FAdm.debugging.fit  =  function () {
      // Configure debugging and development issues
      // Postcondition:
      //    All debugging variables are preset
      // Uses:
      //    this
      //    >< .debugging.loud
      //    >< .review.stamp
      //    >< .trans.stamp
      //    >< .trans.bot.pageName
      //     < .debugging.man
      //     < .debugging.max
      //     < .debugging.dummy
      // 2013-01-14 PerfektesChaos@de.wikipedia
      if ( this.loud === undefined ) {
         this.loud  =  false;
      }
      if ( this.loud ) {
         this.man  =  0;
         this.max  =  200;
         this.say  =  "fileAdm";
         if ( this.dummy === undefined ) {
            this.dummy  =  "Wikipedia:Dateiwartung/Werkzeug/"
                           + "Programmierung/";
         }
//       this.dummy  =  false;
         if ( this.dummy ) {
            FAdm.review.stamp        =  this.dummy
                                        + "Vorlage:" + FAdm.review.stamp;
            FAdm.trans.stamp         =  this.dummy
                                        + "Vorlage:" + FAdm.trans.stamp;
            FAdm.trans.bot.pageName  =  this.dummy
                                        + FAdm.trans.bot.pageName;
         }
      }
   };   // .debugging.fit()



};   // .bb.debugging()
mediaWiki.libs.fileAdm.bb.debugging( mediaWiki.libs.fileAdm );
delete mediaWiki.libs.fileAdm.bb.debugging;



//-----------------------------------------------------------------------



mediaWiki.libs.fileAdm.bb.all  =  function ( FAdm, mw ) {
   // Basic configuration
   // 2012-06-12 PerfektesChaos@de.wikipedia
   "use strict";
   if ( typeof FAdm.all !== "object" ) {   // overall structure and data
      FAdm.all  =  { lang: { },
                     proj: { },
                     user: { } };
   }
   if ( typeof FAdm.all.lang !== "object" ) {
      FAdm.all.lang  =  { };
   }
   if ( typeof FAdm.all.proj !== "object" ) {
      FAdm.all.proj  =  { };
   }
   if ( typeof FAdm.all.user !== "object" ) {
      FAdm.all.user  =  { };
   }
   FAdm.ns     =  { is:          -9,
             // Should be invariant: meta:Help:Namespace
             // Adaption of ns.n* by switch(wgDBname) in .all.proj. only!
                    nMedia:      -2,
                    nSpecial:    -1,
                    nUser:        2,
                    nProject:     4,
                    nFile:        6,
                    nTemplate:   10,
                    nCat:        14,
                    nOthers1:  -999 };
   FAdm.hover  =  false;
   FAdm.ia     =  false;
   FAdm.key    =  false;



   FAdm.all.userlang  =  {
      // 2012-12-19 PerfektesChaos@de.wikipedia
      "de" :   "de",
      "als" :  "de",
      "bar" :  "de",
      "dsb" :  "de",
      "frr" :  "de",
      "gsw" :  "de",
      "hsb" :  "de",
      "ksh" :  "de",
      "lb" :   "de",
      "nds" :  "de",
      "pdc" :  "de",
      "pdt" :  "de",
      "pfl" :  "de",
      "sli" :  "de",
      "stq" :  "de",
      "vmf" :  "de"
   };   // .all.userlang



   FAdm.all.favorite  =  function () {
      // Guess user language
      // Uses:
      //    this
      //    >  .userlang
      //    mw.config.get()
      // 2012-12-19 PerfektesChaos@de.wikipedia
      var r  =  mw.config.get( "wgUserLanguage" ).toLowerCase(),
          s;
      if (r.length > 4) {   // Remove RFC 1766 subtag from language code
         if (r.charCodeAt(2) === 45) {   // '-'
            r  =  r.substr(0, 2);
         }
      }
      s  =  this.userlang[ r ];
      r  =  ( s ? s : "en" );
      return  r;
   };   // .all.favorite()



   FAdm.all.fit  =  function () {
      // Configure globals
      // Postcondition:
      //    All local and internal and developer variables are preset
      // Uses:
      //     < .str.dbName
      //     < .misc.local
      //    .all.favorite()
      //    .all.proj.any()
      //    mw.config.get()
      //    .all.proj.*()
      //    .all.proj.unknown()
      //    .all.lang.*()
      //    .all.user.*()
      //    .all.fill()
      //    .opt.fit()
      //    .debugging.fit()
      // 2013-01-12 PerfektesChaos@de.wikipedia
      var slang  =  this.favorite();
      this.proj.any();
      FAdm.str.dbName  =  mw.config.get( "wgDBname" );
      switch ( FAdm.str.dbName ) {
         case "dewiki" :
            this.proj[ FAdm.str.dbName ]();
            break;
         case "commonswiki" :
            FAdm.misc.local  =  false;
            // fall through
         default: //
            this.proj.unknown();
      }   // switch wgDBname
      switch ( mw.config.get( "wgContentLanguage" ) ) {
         case "de" :
            this.lang.de();
            break;
         default:
            this.lang.en();
      }   // switch wgContentLanguage
      this.user[ slang ]();
      this.fill();
      FAdm.opt.fit();
      FAdm.debugging.fit();
   };   // .all.fit()



   FAdm.all.proj.any  =  function () {
      // Configure default strings and data for any project
      // Postcondition:
      //    General defaults, may be overwritten in particular project
      // Uses:
      //     < .batch.clock
      //     < .batch.maxTitles
      //     < .batch.watch
      //     < .batch.watchQ
      //     < .batch.watchT
      //     < .guide.cats
      //     < .guide.multiQuery
      //     < .guide.selTemplate
      //     < .queer.textarea
      //     < .review.selTemplate
      //     < .trans.subject
      //     < .trans.idle.id
      // 2011-10-27 PerfektesChaos@de.wikipedia
      FAdm.batch.clock         =  "//upload.wikimedia.org/"
                                  + "wikipedia/commons"
                                  + "/d/de/Ajax-loader.gif";
      FAdm.batch.maxTitles     =  50;
      FAdm.batch.watch         =  false;
      FAdm.batch.watchQ        =  "watch";
      FAdm.batch.watchT        =  "watch";
      FAdm.cat.regexpMaintain  =  false;
      FAdm.cat.reMaintain      =  false;
      FAdm.cat.start           =  false;
      FAdm.file.info           =  { };
      FAdm.guide.cats          =  {
       none:     "border: solid 3px #FF0000; background-color: #E9967A",
       category: "background-color: #FF69B4",
       checking: [ false,
                   "border: solid 2px #FF0000" ],
       checkX:   "border:solid 2px #FF0000;background-color:#CFFFCF",
       invalid:  "border:solid 4px #FFA000;background-color:#FF1493",
       license:  [ false,
                   "border:solid 2px #006000;background-color:#80FF80" ],
       review0:  [ false,
                   "background-color: #FF8C00" ],
       review1:  [ false,
                   "background-color: #F0E68C" ],
       review1X: "background-color: #A0A0A0",
       review2:  [ false,
                   "background-color: #CFFFCF" ],
       transfer: [ false,
                   "border:solid 2px #0000FF;background-color:#CFFFCF" ],
       transfix: [ false,
                   "border:solid 2px #0000FF;background-color:#D0D0FF" ],
       transit:  [ false,
                   "border:solid 2px #0000FF;background-color:#F0E68C" ],
       transmit: [ false,
                   "border:solid 2px #0000FF;background-color:#CFFFCF" ],
       transnot: "border:solid 2px #0000FF;background-color:#C0C0C0",
       trash:    [ false,
                   "border:solid 2px #0000FF;background-color:#FF8080" ],
       lazyRE:   true };
      FAdm.guide.multiQuery    =  5;
      FAdm.guide.selTemplate   =  "#fileAdm_Guide-collection";
      FAdm.queer.opts          =  false;
      FAdm.queer.textarea      =  [3, 40];
      FAdm.review.selTemplate  =  "#fileAdm_Review";
      FAdm.trans.subject       =  "Transfer to Commons by Bot";
      FAdm.trans.idle.id       =  "fileAdm_Transfer_idle";
      FAdm.trans.vsn.sel       =  ".multiVersion";
   };   // .all.proj.any()



   FAdm.all.proj.dewiki  =  function () {
      // Configure strings and data for German language Wikipedia
      // Postcondition:
      //    German language Wikipedia adaption
      // Uses:
      //     < .*.*
      // 2013-01-26 PerfektesChaos@de.wikipedia
      FAdm.batch.reBlacklist       =  "[_.;,]Werbung[_.;,]";
      FAdm.batch.selfSign          =  "Werkzeug";
      FAdm.cat.hidden              =  "Kategorie:Versteckt";
      FAdm.cat.reMaintain          =  "(Datei:Datei-Wartung)";
      FAdm.cat.reNoParSuggest      =  "(^ *(Wikipedia|Logo \\())";
      FAdm.cat.selTemplate         =  "#Dateikategorie";
      FAdm.cat.stamp               =  "Dateikategorie";
      FAdm.cat.start               =  "Datei:";
      FAdm.edit.defaultsort        =  "SORTIERUNG";
      FAdm.file.info.template      =  [ "Information",
                                        "Beschreibung",
                                        "Quelle",
                                        "Urheber",
                                        "Datum",
                                        "Genehmigung",
                                        "Andere Versionen" ];
      FAdm.file.info.align         =  55;
      FAdm.file.info.reTmpl        =  false;
      FAdm.file.stNoCommons        =  "NoCommons";
      FAdm.file.stNowCommons       =  "NowCommons";
      FAdm.file.replace            =
                                 [ [ "{{ *[bB]ild-SH *}}",
                                     "{{Bild-PD-Schöpfungshöhe}}" ],
                                   [ "{{[cC]opy to Wikimedia Commons}}",
                                     "{{Commonsfähig}}" ],
                                   [ "{{ *[dD](ÜP|üp) *(}}|\\|)",
                                   "{{Dateiüberprüfung$2" ],
                                   [ "{{ *[dD]ateiüberprüfung *(}}|\\|)",
                                     "{{Dateiüberprüfung$1" ],
                                   [ "{{ *[Ss]vg *}}",
                                     "{{In SVG konvertieren}}" ],
                                   [ "{{ *[mM]angelhafte[ _]SVG *}}",
                                     "{{Mangelhafte Vektorisierung}}" ],
                                   [ "{{ *[nN]C *(}}|\\|)",
                                     "{{NowCommons$1" ],
                                   [ "{{ *[nN]ow[ _]Commons *(}}|\\|)",
                                     "{{NowCommons$1" ],
                                   [ "{{ *[nN]owcommons *(}}|\\|)",
                                     "{{NowCommons$1" ],
                                   [ "^=([^=\n].*[^=\n])= *\n",
                                     "==$1==\n" ],
                                   [ "\n=([^=\n].*[^=\n])= *\n",
                                     "\n==$1==\n" ],
                                   [ "^(=+) *([^ =\n].*[^ =\n]) *\\1\n",
                                     "$1 $2 $1\n" ],
                                   [ "\n(=+) *([^ =\n].*[^ =\n]) *\\1\n",
                                      "\n$1 $2 $1\n" ] ];
      FAdm.file.selCommons         =  "#commons_descr";
      FAdm.file.selNowCommons      =  "#Vorlage_NowCommons";
                                   // ".*" => beginnend mit
      FAdm.guide.cats.checking[0]  =  "Wikipedia:Dateiüberprüfung.*";
      FAdm.guide.cats.license[0]   =  [ "Datei:By.*",      // Beginn mit
                                        "Datei:CC-by.*",   // Beginn mit
                                        "Datei:CC-Zero",
                                        "Datei:Frei",
                                        "Datei:GFDL",
                                        "Datei:LogoSH",
                                        "Datei:Musik-PD .*",
                                        "Datei:Musikzitat",
                                        "Datei:Public Domain .*",
                                        "Datei:Wikimedia-Copyright" ];
      FAdm.guide.cats.review0[0]   =  "Datei:NoCommons";
      FAdm.guide.cats.review1[0]   =  "Datei:Zweitprüfung ausstehend";
      FAdm.guide.cats.review2[0]   =  "Datei:Geprüfte Datei";
      FAdm.guide.cats.transfer[0]  =  [ "Datei:By",
                                        "Datei:CC-Zero",
                                        "Datei:Frei",
                                        "Datei:GFDL",
                                        "Datei:Public Domain .*" ];
      FAdm.guide.cats.transfix[0]  =  "Datei:Nach Commons verschieben"
                                      + " (bestätigt)";
      FAdm.guide.cats.transit[0]   =  "Datei:Nach Commons verschieben"
                                      + " (Bestätigung nötig)";
      FAdm.guide.cats.transmit[0]  =  "Datei:Commonsfähig";
      FAdm.guide.cats.trash[0]     =  "Datei:NowCommons.*"; // Beginn mit
      FAdm.guide.linkState         =  { hotkey: "s" };
      FAdm.ns.nOthers1             =  100;   // Portal:
      FAdm.opt.keep                =  0;
      FAdm.opt.page.id             =  6425961;
      FAdm.queer.opts              =
         [ // count from 0; hints: w:de:User:Ireas/düp-setzen-monobook.js
           { key:  "Quelle",
             hint: "Wenn nicht deutlich wird, "
                   + "woher der Uploader die Datei hat" },
           { key:  "Urheber",
             hint: "Wenn nicht deutlich wird, "
                   + "wer der Urheber der Datei ist" },
           { key:  "Lizenz",
             hint: "Wenn die Datei nicht"
                   + " unter einer freien Lizenz veröffentlicht wurde" },
           { key:  "Freigabe",
             hint: "Wenn nicht deutlich wird, dass"
                   + " der Urheber einer freien Lizenz zugestimmt hat" },
           { key:  "Gezeigtes Werk",
             hint: "Wenn nicht klar ist, "
                   + "dass der Urheber des Originalwerks "
                   + "einer freien Lizenz zugestimmt hat" },
           { key:  "1923",
             hint: "Für Bilder nach der 1923er-Regel, "
                   + "deren Diskussionslink fehlt." },
           { key:  "Besonderer Fall",
             hint: "Wenn ein besonderer Fall vorliegt "
                   + "(persönliche Benachrichtigung)" } ];
      FAdm.queer.stamp             =  "Dateiüberprüfung";
      FAdm.queer.specific          =  "Hinweis";
      FAdm.queer.quest             =  [ FAdm.queer.stamp,
                                        "DÜP",
                                        "Düp",
                                        "DÜp",
                                        "DüP" ];
      FAdm.queer.stampNotified     =  "Dateiüberprüfung/benachrichtigt"
                                      + " (Text)";
      FAdm.review.selTemplate      =  "#filereview-successful";
      FAdm.review.stamp            =  "Geprüfte Datei";
      FAdm.trans.stable            =  "Commonsfähig";
      FAdm.trans.stamp             =  "Nach Commons verschieben"
                                      + " (bestätigt)";
      FAdm.trans.suitable          =  "Nach Commons verschieben"
                                      + " (Bestätigung nötig)";
      FAdm.trans.bot.pageName      =  "Wikipedia:"
                                      + "Commons-Transfer per Bot"
                                      + "/Anfragen";
      FAdm.users.r                 =  6358806;   // real: 6358806
      FAdm.users.t                 =  6426331;   // real: 6426331
      FAdm.wins.lot                =  true;
   };   // .all.proj.dewiki()



/*
      file.info.template      =  [ "Information",
                                   "Description",
                                   "Source",
                                   "Author",
                                   "Permission",
                                   "other_versions" ];
      file.info.align         =  1;
*/



   FAdm.all.proj.unknown  =  function () {
      // Disable any major start function if current project is unknown
      // Postcondition:
      //    Any action is disabled
      // Uses:
      //     < .cat.action()
      //     < .file.action()
      //     < .guide.action()
      // 2011-10-21 PerfektesChaos@de.wikipedia
      FAdm.cat.action    =  false;
      FAdm.file.action   =  false;
      FAdm.guide.action  =  false;
   };   // .all.proj.unknown()



   FAdm.all.lang.de  =  function () {
      // Configure message strings / German users; visible to other users
      // Postcondition:
      //    German texts are set
      // Uses:
      //     < see .all.lang.en
      // 2011-12-07 PerfektesChaos@de.wikipedia
      FAdm.edit.summary0         =  "kosmetische Änderungen";
      FAdm.queer.summary         =  "Dateiüberprüfung";
      FAdm.review.summary1       =  "Erste Dateiprüfung";
      FAdm.review.summary2       =  "Zweite Dateiprüfung";
      FAdm.trans.summary         =  "Markierung für CTB gesetzt";
      FAdm.trans.bot.sayConfirm  =  "Bestätige Transferwunsch";
      FAdm.trans.vsn.say         =  "Mehrfache Dateiversionen";
   };   // .all.lang.de()



   FAdm.all.lang.en  =  function () {
      // Configure project message strings for English and default users
      // Postcondition:
      //    English texts are set
      // Uses:
      //     < .edit.summary0
      //     < .queer.summary
      //     < .review.summary1
      //     < .review.summary2
      //     < .trans.summary
      //     < .trans.bot.sayConfirm
      //     < .trans.vsn.say
      // 2011-12-07 PerfektesChaos@de.wikipedia
      FAdm.edit.summary0         =  "cosmetic changes";
      FAdm.queer.summary         =  "File check";
      FAdm.review.summary1       =  "First file review";
      FAdm.review.summary2       =  "Second file review";
      FAdm.trans.summary         =  "Marked for transfer to Commons";
      FAdm.trans.bot.sayConfirm  =  "Confirm transfer request";
      FAdm.trans.vsn.say         =  "Multiple file versions";
   };   // .all.lang.en()



   FAdm.all.user.de  =  function () {
      // Configure UI strings for German users
      // Postcondition:
      //    German texts are set
      // Uses:
      //     < see .all.user.en
      // 2012-12-19 PerfektesChaos@de.wikipedia
      FAdm.batch.sayActive        =  "Kommuniziere mit dem GROSSEN GURU";
      FAdm.batch.sayCurrentVsn    =  "Aktuelle Version anzeigen";
      FAdm.batch.sayModified      =  "Änderung vorgenommen";
      FAdm.batch.sayNoText        =  "Kein Text";
      FAdm.batch.sayNothing2do    =  "Nichts zu tun";
      FAdm.cat.sayNoTemplate      =  "Fehlende Vorlage";
      FAdm.guide.linkState.hint   =  "Jede Datei nach Status markieren";
      FAdm.guide.linkState.title  =  "Datei-Status zeigen";
      FAdm.guide.toggleImg        =
                                   { hint:   "Miniaturbilder verbergen?",
                                     hotkey: "-",   // m=move
                                     off:    "zeigen",
                                     on:     "ausblenden",
                                     title:  "Miniaturbilder" };
      FAdm.guide.toggleTgt        =
                                   { hint:   "Links in anderes Fenster?",
                                     hotkey: "*",
                                     off:    "gleich",
                                     on:     "separat",
                                     title:  "Zielfenster" };
      FAdm.guide.xClm             =
                                   { hint:   "Spalte mit Direktlinks?",
                                     hotkey: "<",
                                     title:  "Bearbeitung" };
      FAdm.queer.link             =
                                   { hint:   "Dateiüberprüfung",
                                     hotkey: "ü",
                                     title:  "DÜP" };
      FAdm.queer.soft             =  "Bearbeiten mit DÜP-Markierung";
      FAdm.queer.shift            =  "Markiere als DÜP";
      FAdm.queer.subject          =  "DÜP";
      FAdm.review.scatter         =  "Noch keine Kategorie";
      FAdm.review.scope           =  "Ohne NoCommons";
      FAdm.review.second          =  "Bereits zweimal geprüft";
      FAdm.review.self            =  "Du hast hier bereits geprüft";
      FAdm.review.setup           =  "Bisher noch nie geprüft";
      FAdm.review.shift           =  "Markiere als geprüft";
      FAdm.review.signed          =  "Erste Prüfung bereits erfolgt";
      FAdm.review.soft            =  "Bearbeiten mit Prüfmarkierung";
      FAdm.review.subject         =  "Dateiprüfung";
      FAdm.review.sucks           =  "Dateiüberprüfung";
      FAdm.str.sayConflict        =  "KONFLIKT";
      FAdm.trans.sayNo            =  "Seite ist gleichzeitig NoCommons"
                                     + " und für Commons vorgesehen";
      FAdm.trans.shift            =  "Markiere für CTB";
      FAdm.trans.soft             =  "Bearbeiten mit CTB-Markierung";
      FAdm.trans.sucks            =  "Konflikt mit NoCommons";
      FAdm.trans.bot.save         =  "Speichern++";
      FAdm.trans.idle.say         =  "Erneuter Transfer";
      FAdm.trans.idle.sleep       =  "Keine Änderung seit 3 Tagen";
   };   // .all.user.de()



   FAdm.all.user.en  =  function () {
      // Configure UI strings for English and default users
      // Postcondition:
      //    English texts are set
      // Uses:
      //     < .batch.sayActive
      //     < .batch.sayCurrentVsn
      //     < .batch.sayModified
      //     < .batch.sayNoText
      //     < .batch.sayNothing2do
      // 2011-10-10 PerfektesChaos@de.wikipedia
      FAdm.batch.sayActive        =  "Contacting Wiki Server";
      FAdm.batch.sayCurrentVsn    =  "Show current version";
      FAdm.batch.sayModified      =  "Modification performed";
      FAdm.batch.sayNoText        =  "No Text";
      FAdm.batch.sayNothing2do    =  "Nothing to do";
      FAdm.cat.sayNoTemplate      =  "Template missing";
      FAdm.guide.linkState.hint   =  "Mark any file by state";
      FAdm.guide.linkState.title  =  "Show file state";
      FAdm.guide.toggleImg        =
                                   { hint:   "Hide thumbnails?",
                                     hotkey: "-",
                                     off:    "(hide)",
                                     on:     " (show)",
                                     title:  "Thumbnails" };
      FAdm.guide.toggleTgt        =
                                   { hint:   "Link into other window?",
                                     hotkey: "*",
                                     off:    "(same)",
                                     on:     "(different)",
                                     title:  "Target window" };
      FAdm.guide.xClm             =
                                   { hint:   "Column with direct links?",
                                     hotkey: "<",
                                     title:  "Editing" };
      FAdm.queer.link             =
                                   { hint:   "File checking needed?",
                                     hotkey: "9",
                                     title:  "File checking" };
      FAdm.queer.soft             =  "Edit with file check mark";
      FAdm.queer.shift            =  "Mark for file check";
      FAdm.queer.subject          =  "File check";
      FAdm.review.scatter         =  "No category yet";
      FAdm.review.scope           =  "NoCommons not seen";
      FAdm.review.second          =  "Two file reviews done";
      FAdm.review.self            =  "You have reviewed here already";
      FAdm.review.setup           =  "Never reviewed yet";
      FAdm.review.shift           =  "Mark as reviewed";
      FAdm.review.signed          =  "First review already done";
      FAdm.review.soft            =  "Edit with review mark";
      FAdm.review.subject         =  "File review";
      FAdm.review.sucks           =  "File check";
      FAdm.str.sayConflict        =  "CONFLICT";
      FAdm.trans.sayNo            =  "File is supposed to be both"
                                     + " NoCommons and on Commons";
      FAdm.trans.shift            =  "Mark for CTB";
      FAdm.trans.soft             =  "Edit with CTB mark";
      FAdm.trans.sucks            =  "Conflict with NoCommons";
      FAdm.trans.bot.save         =  "Save++";
      FAdm.trans.idle.say         =  "New attempt to transfer";
      FAdm.trans.idle.sleep       =  "No changes within 3 days";
   };   // .all.user.en()



   FAdm.all.fill  =  function () {
      // Configure internal globals   *** developers only ***
      // Postcondition:
      //    All internal variables are preset
      // Uses:
      //    >  .opt.keep
      //    >  .guide.lessMini
      //    >  .wins.lot
      //    >  .batch.watchQ
      //    >  .batch.watchT
      //    >  .obj
      //    >  .type
      // Requires: JavaScript 1.3   fromCharCode()
      // 2013-01-19 PerfektesChaos@de.wikipedia
      FAdm.batch.api          =  false;
      FAdm.batch.page         =  false;
      FAdm.batch.styleButton  =  "background:      #D0D0D0;" +
                                 "color:           #000000;" +
                                 "font-size:       100%;" +
                                 "font-weight:     normal;" +
                                 "text-decoration: none;" +
                                 "padding:         2px;" +
                                 "border-style:    solid;" +
                                 "border-width:    2px;" +
                                 "border-color:    #E0E0E0 " +  // top
                                                  "#E0E0E0 " +  // right
                                                  "#707070 " +  // bottom
                                                  "#707070;";   // left
      FAdm.cat.tools          =  false;
      FAdm.file.cats          =  false;
      FAdm.file.lone          =  true;
      FAdm.file.mode          =  0;
      FAdm.file.type          =  false;
      FAdm.guide.lessMini     =  false;
      FAdm.guide.jumpQuery    =  -1;
      FAdm.guide.stateFilter  =  false;
      FAdm.guide.stateIndex   =  -1;
      FAdm.guide.stateMax     =  -1;
      FAdm.guide.stateMin     =  -1;
      FAdm.guide.stateQuery   =  false;
      FAdm.guide.styleImg     =  false;
      FAdm.guide.xClm.live    =  false;
      FAdm.guide.$mins        =  false;
      FAdm.misc.local         =  true;
      FAdm.ns.map             =  false;
      FAdm.ns.reTemplate      =  false;
      FAdm.ns.sCat            =  false;
      FAdm.ns.sFile           =  false;
      FAdm.ns.sTemplate       =  false;
      FAdm.ns.sUser           =  false;
      FAdm.opt.memory         =  { env: "memory",
                                   typ: "number",
                                   val: FAdm.opt.keep };
      FAdm.opt.lessMini       =  { env: "lessMini",
                                   typ: "boolean",
                                   val: FAdm.guide.lessMini };
      FAdm.opt.multiWin       =  { env: "multiWin",
                                   typ: "boolean",
                                   val: FAdm.wins.lot };
      FAdm.opt.watchQ         =  { env: "watchQ",
                                   typ: "choice",
                                   val: FAdm.batch.watchQ };
      FAdm.opt.watchT         =  { env: "watchT",
                                   typ: "choice",
                                   val: FAdm.batch.watchT };
      FAdm.queer.stuck        =  false;
      FAdm.str.action         =  false;
      FAdm.str.artPath        =  false;
      FAdm.str.script         =  "javascript"
                                 + String.fromCharCode( 58 );
      FAdm.str.call           =  FAdm.str.script + FAdm.obj + "."
                                 + FAdm.type + ".";
      FAdm.str.page.content   =  false;
      FAdm.str.page.id        =  false;
      FAdm.str.page.name      =  false;
      FAdm.str.page.rvtime    =  false;
      FAdm.str.page.title     =  false;
      FAdm.str.page.urlEnc    =  false;
      FAdm.trans.bot.commons  =  false;
      FAdm.trans.bot.discard  =  false;
      FAdm.trans.bot.post     =  false;
      FAdm.trans.bot.queue    =  false;
      FAdm.trans.bot.rvtime   =  false;
      FAdm.trans.bot.update   =  false;
      FAdm.trans.bot.$xSave   =  false;
      FAdm.users.i            =  false;
      FAdm.users.n            =  false;
      FAdm.users.w            =  false;
      FAdm.wins.single        =  "fileSingle";
      FAdm.wins.toolOut       =  "fileTools";
   };   // .all.fill()



};   // .bb.all()
mediaWiki.libs.fileAdm.bb.all( mediaWiki.libs.fileAdm, mediaWiki );
delete mediaWiki.libs.fileAdm.bb.all;



//-----------------------------------------------------------------------



mediaWiki.libs.fileAdm.bb.batch  =  function ( FAdm, mw ) {
   // API communication support
   // 2012-06-12 PerfektesChaos@de.wikipedia
   "use strict";
   if ( typeof FAdm.batch !== "object" ) {
      FAdm.batch  =  { };
   }



   FAdm.batch.failed  =  function ( about ) {
      // API retrieval failed
      // Precondition:
      //    about  -- reason
      // Postcondition:
      //    message is displayed
      // Uses:
      //    jQuery()
      //    .misc.message()
      // Remark: Used as event handler -- 'this' is not FAdm.batch
      // 2011-08-30 PerfektesChaos@de.wikipedia
      var style  =  "color: #FF0000; border: solid 2px; width: auto; "
                    + "padding: 5px; margin-top: 10px;";
      var $box   =  jQuery( "<div />" );
      var $head  =  jQuery( "<strong />" );
      $head.text( about );
      $box.append( $head );
      $box.attr( "style", style );
      FAdm.misc.message( $box, "fileAdmError", true );
   };   // .batch.failed()



   FAdm.batch.failure  =  function ( e, jqXHR, settings, thrown ) {
      // Error handler for ajax requests
      // Precondition:
      //    Handler
      // Postcondition:
      //    message is displayed to the user
      // Uses:
      //    >  .debugging
      //    .batch.failed()
      // Remark: Used as event handler -- 'this' is not FAdm.batch
      // 2011-11-30 PerfektesChaos@de.wikipedia
      mw.log( FAdm.debugging,  ".batch.failure() " + settings,
              3,
              jqXHR );
      FAdm.batch.failed();
   };   // .batch.failure()



   FAdm.batch.faith  =  function () {
      // Entertain waiting user while communicating
      // Postcondition:
      //    message is displayed
      //    Sing a song; show a Mickey Mouse movie
      // Uses:
      //    >  .batch.clock
      //    >  .batch.sayActive
      //    .misc.message()
      // 2011-08-30 PerfektesChaos@de.wikipedia
      var style  =  "color: #7B68EE; border: solid 2px; width: auto; "
                    + "padding: 5px; margin-top: 10px; height: 40px;";
      var $box   =  jQuery( "<div />" );
      var $head  =  jQuery( "<strong />" );
      var $img   =  jQuery( "<img />" );
      $img.attr( "height", "40" );
      $img.attr( "src", FAdm.batch.clock );
      $box.append( $img );
      $head.text( "... " + FAdm.batch.sayActive + " ..." );
      $box.append( $head );
      $box.attr( "style", style );
      FAdm.misc.message( $box, "fileAdmAPI", true );
   };   // .batch.faith()



   FAdm.batch.feed  =  function ( action ) {
      // Retrieve displayed page content by API, launch particular action
      // Precondition:
      //    action  -- (edit) function to be executed
      // Postcondition:
      //    Follow-up procedure is launched
      // Uses:
      //    >  .batch.sayNoText
      //    >  .ns.is
      //    >  .ns.nFile
      //    >< .batch.api
      //    >< .str.page.name
      //    >< .str.page.id
      //    >< .misc.pageid
      //     < .str.page.content
      //     < .str.page.rvtime
      //     < .batch.rvtime
      //    .str.fromNum()
      //    (.batch.force)
      //    (.trans.bot.feeder)
      //    (.batch.failed)
      //    mw.util.wikiScript()
      //    mw.config.get()
      //    jQuery.getJSON()
      // 2012-01-09 PerfektesChaos@de.wikipedia
      var query;
      if ( ! FAdm.batch.api ) {
         FAdm.batch.api  =  mw.util.wikiScript( "api" );
      }
      if ( ! FAdm.str.page.name ) {
         FAdm.str.page.name  =  mw.config.get( "wgPageName" );
      }
      if ( ! FAdm.str.page.id ) {
         if ( typeof( FAdm.misc.pageid )  !==  "number" ) {
            FAdm.misc.pageid  =  mw.config.get( "wgArticleId" );
         }
         FAdm.str.page.id  =  FAdm.str.fromNum( FAdm.misc.pageid );
      }
      query   =  { action:  "query",
                   prop:    "revisions",
                   rvprop:  "content|timestamp",
                   rvlimit: 1,
                   format:  "json",
                   titles:  FAdm.str.page.name };
      jQuery.getJSON( FAdm.batch.api,
                      query,
                      function ( arrived ) {
                         var got  =  arrived.query;
                         if ( got ) {
                            got  =  got.pages[ FAdm.str.page.id ];
                            if ( got ) {
                               got  =  got.revisions[ "0" ];
                            }
                         }
                         if ( got ) {
                            FAdm.str.page.content = got[ "*" ];
                            FAdm.str.page.rvtime  = got.timestamp;
                            FAdm.batch.rvtime     = FAdm.str.page.rvtime;
                            if ( FAdm.str.page.content ) {
                               FAdm.batch.force( false, action );
                            } else {
                               got  =  false;
                            }
                         }
                         if ( got ) {
                            if ( FAdm.ns.is === FAdm.ns.nFile ) {
                               FAdm.trans.bot.feeder();
                            }
                         } else {
                            FAdm.batch.failed( FAdm.batch.sayNoText );
                         }
                      } );
   };   // .batch.feed()



   FAdm.batch.fetch  =  function ( access, action ) {
      // Retrieve page content and timestamp, then perform action
      // Precondition:
      //    access  -- page name
      //    action  -- edit function to be executed afterwards
      // Postcondition:
      //    Edit procedure is performed if appropriate
      // Uses:
      //    >< .batch.api
      //    jQuery.getJSON()
      // 2011-10-11 PerfektesChaos@de.wikipedia
      var query  =  { action:       "query",
                      prop:         "revisions",
                      rvprop:       "content|timestamp",
                      rvlimit:      1,
                      indexpageids: true,
                      titles:       access,
                      format:       "json" };
      if ( ! FAdm.batch.api ) {
         FAdm.batch.api  =  mw.util.wikiScript( "api" );
      }
      jQuery.getJSON( FAdm.batch.api,
                      query,
                      action );
   };   // .batch.fetch()



   FAdm.batch.fine  =  function ( arrived, about, answer ) {
      // API modification succeeded
      // Precondition:
      //    arrived  -- API data
      //    about    -- textStatus
      //    answer   -- jqXHR answer
      // Postcondition:
      //    Success message is displayed
      // Uses:
      //    >  .batch.sayCurrentVsn
      //    >  .batch.sayModified
      //    >  .str.page.name
      //    mw.util.wikiGetlink()
      //    jQuery()
      //    .misc.message()
      // Remark: Used as event handler -- 'this' is not FAdm.batch
      // 2013-01-07 PerfektesChaos@de.wikipedia
      var state  =  "HTTP error";
      var style;
      var $box;
      var $head;
      var $info;
      var $link;
      if ( answer ) {
         if ( answer.status === 200 ) {
            if ( arrived.indexOf( "newtimestamp=" )  >  0 ) {
               state  =  false;
            } else {
//             state  =  "Invalid request";
               state  =  false;
            }
         } else {
            state  =  state + " " + answer.status;
         }
      }
      if ( state ) {
         FAdm.batch.failed( state );
      } else {
         style  =  "color: #007000; border: solid 2px; "
                   + "width: auto; padding: 5px; margin-top: 10px;";
         $box   =  jQuery( "<div />" );
         $head  =  jQuery( "<strong />" );
         $info  =  jQuery( "<p />" );
         $link  =  jQuery( "<a />" );
         $head.text( FAdm.batch.sayModified );
         $box.append( $head );
         $link.text( FAdm.batch.sayCurrentVsn );
         $link.attr( "href",
                     mw.util.wikiGetlink( FAdm.str.page.name ) );
         $info.append( $link );
         $box.append( $info );
         $box.attr( "style", style );
         FAdm.misc.message( $box, "fileAdmDone", true );
      }
   };   // .batch.fine()



   FAdm.batch.flash  =  function ( action, await ) {
      // Perform page modification by API
      // Precondition:
      //    action  -- edit function to be executed
      //    await   -- entertain waiting user while communicating
      //    Current page is subject of edit
      // Postcondition:
      //    Procedure is launched
      // Uses:
      //    .batch.faith()
      //    .batch.feed()
      // 2011-10-10 PerfektesChaos@de.wikipedia
      if ( await ) {
         FAdm.batch.faith();
      }
      FAdm.batch.feed( action );
   };   // .batch.flash()



   FAdm.batch.force  =  function ( adjust, action ) {
      // Perform modification by API
      // Precondition:
      //    adjust  -- false:     take page content from str.page.content
      //               Array[3]:  [0]  -- modified page content
      //                          [1]  -- summary
      //                          [2]  -- true: minor edit
      //    action  -- edit function to be executed, transforms adjust
      //               false if adjust is to be taken as is
      //    Current page will be modified, or batch.page if set
      // Postcondition:
      //    Modification is performed if appropriate
      // Uses:
      //    >  .str.page.content
      //    >  .str.page.rvtime
      //    >  .batch.watch
      //    >  .batch.selfSign
      //    >  .vsn
      //    >  .batch.sayNothing2do
      //    >< .batch.page
      //    >< .batch.rvtime
      //    >< .str.page.name
      //    (.batch.fine)
      //    .batch.failed()
      //    mw.config.get()
      //    mw.user.tokens.get()
      //    jQuery().post()
      // Remark: Used as event handler -- 'this' is not FAdm.batch
      // 2011-10-23 PerfektesChaos@de.wikipedia
      var change  =  false;
      var doit;
      var wl;
      if ( adjust ) {
         change  =  adjust;
      } else {
         change  =  FAdm.str.page.content;
      }
      if ( action && change ) {
         change  =  action( change );
      }
      if ( ! FAdm.batch.page ) {
         if ( ! FAdm.str.page.name ) {
            FAdm.str.page.name  =  mw.config.get( "wgPageName" );
         }
         FAdm.batch.page  =  FAdm.str.page.name;
      }
      if ( ! FAdm.batch.rvtime ) {
         FAdm.batch.rvtime  =  FAdm.str.page.rvtime;
      }
      if ( change ) {
         wl    =  ( FAdm.batch.watch ? FAdm.batch.watch
                                     : "preferences" );
         doit  =  { action:        "edit",
                    token:         mw.user.tokens.get( "editToken" ),
                    title:         FAdm.batch.page,
                    text:          change[0],
                    summary:       change[1]
                                   + " * " + FAdm.batch.selfSign
                                   + " fileAdm " + FAdm.vsn,
                    watchlist:     wl,
                    minor:         change[2],
                    basetimestamp: FAdm.batch.rvtime,
                    nocreate:      true };
         jQuery.post( FAdm.batch.api, doit, FAdm.batch.fine );
      } else {
         FAdm.batch.failed( FAdm.batch.sayNothing2do );
      }
   };   // .batch.force()



};   // .bb.batch()
mediaWiki.libs.fileAdm.bb.batch( mediaWiki.libs.fileAdm, mediaWiki );
delete mediaWiki.libs.fileAdm.bb.batch;



//-----------------------------------------------------------------------



mediaWiki.libs.fileAdm.bb.cat  =  function ( FAdm, mw ) {
   // Category page support
   // 2012-06-12 PerfektesChaos@de.wikipedia
   "use strict";
   if ( typeof FAdm.cat !== "object" ) {
      FAdm.cat  =  { };
   }



   FAdm.cat.action  =  function () {
      // Opening file category page
      // Precondition:
      //    Current page is supposed to be a file category page
      //    window.document is ready
      //    Page title begins with .cat.start but not only
      // Postcondition:
      //    Procedures are performed.
      //    Returns void(0), as required in GUI action, if browser window
      // Uses:
      //    >  .cat.selTemplate
      //    >  .cat.sayNoTemplate
      //    >  .cat.stamp
      //    >< .str.action
      //    .guide.fill()
      //    .cat.fenced()
      //    .cat.find()
      //    .cat.format()
      //    mw.config.get()
      // Remark: Used as event handler -- 'this' is not FAdm.cat
      // 2012-08-30 PerfektesChaos@de.wikipedia
      var say;
      var $t;
      if ( ! FAdm.str.action ) {
         FAdm.str.action  =  mw.config.get( "wgAction" );
      }
      switch ( FAdm.str.action ) {
         case "view" :
            $t  =  jQuery( FAdm.cat.selTemplate );
            FAdm.guide.fill();
            if ( ! $t.length ) {
               if ( ! FAdm.cat.fenced( false ) ) {
                   say  =  "<div class='error'"
                           + " style='border: solid 1px; width: auto; "
                           +         "margin-top: 10px'>"
                           + FAdm.cat.sayNoTemplate + ": "
                           + FAdm.cat.stamp + "</div>";
                   FAdm.misc.message( say, "fileAdmNoTemplate", true );
               }
            }
            FAdm.cat.find( true );
            break;
         case "edit" :
            FAdm.cat.format();
            break;
      }   // switch wgAction
      return void(0);
   };   // .cat.action()



   FAdm.cat.family  =  function ( ask ) {
      // What kind of category is described by name?
      // Precondition:
      //    ask  -- string with category title
      // Postcondition:
      //    Returns  -1  if member of hidden or maintenance category
      //              1  if otherwise member of file category
      //              0  if not member of any known category class
      // Uses:
      //    >  .cat.hidden
      //    >  .cat.regexpMaintain
      //    >  .cat.start
      //    >  .guide.cats
      //    >  .guide.cats.checking
      //    >  .guide.cats.review0
      //    >  .guide.cats.review1
      //    >  .guide.cats.review2
      //    >  .guide.cats.license
      //    >  .guide.cats.transfer
      //    >  .guide.cats.transfix
      //    >  .guide.cats.transit
      //    >  .guide.cats.transmit
      //    >  .guide.cats.trash
      //    .guide.fulfil()
      // 2011-11-30 PerfektesChaos@de.wikipedia
      var gcs;
      var r  =  0;
      if ( ask === FAdm.cat.hidden ) {
         r  =  -1;
      } else if ( FAdm.cat.regexpMaintain ) {
         if ( FAdm.cat.regexpMaintain.test( ask ) ) {
            r  =  -1;
         }
      }
      if ( ! r ) {
         gcs  =  FAdm.guide.cats;
         r  =  -1;
         if ( FAdm.guide.fulfil( ask, gcs.checking ) ) {
         } else if ( FAdm.guide.fulfil( ask, gcs.review0 ) ) {
         } else if ( FAdm.guide.fulfil( ask, gcs.review1 ) ) {
         } else if ( FAdm.guide.fulfil( ask, gcs.review2 ) ) {
         } else if ( FAdm.guide.fulfil( ask, gcs.license ) ) {
         } else if ( FAdm.guide.fulfil( ask, gcs.transfer ) ) {
         } else if ( FAdm.guide.fulfil( ask, gcs.transfix ) ) {
         } else if ( FAdm.guide.fulfil( ask, gcs.transit ) ) {
         } else if ( FAdm.guide.fulfil( ask, gcs.transmit ) ) {
         } else if ( FAdm.guide.fulfil( ask, gcs.trash ) ) {
         } else {
            r  =  0;
         }
      }
      if ( ! r ) {
         if ( FAdm.cat.start ) {
            if ( ask.indexOf( FAdm.cat.start )  ===  0 ) {
               r  =  1;
            }
         }
      }
      return r;
   };   // .cat.family()



   FAdm.cat.fenced  =  function ( area ) {
      // Is current category member of a maintenance category?
      // Precondition:
      //    area  -- false: view   string: edit/submit; article text
      //    Current page is a category.
      // Postcondition:
      //    Returns  true  iff member of hidden or maintenance category
      // Uses:
      //    >  .ns.nCat
      //    >  .cat.reMaintain
      //    >  .guide.selTemplate
      //    >  .guide.cats
      //    >  .cat.hidden
      //    >< .ns.sCat
      //    >< .file.cats
      //    >< .cat.regexpMaintain
      //    .ns.fetch()
      //    .guide.furnish()
      //    .cat.family()
      //    mw.config.get()
      // 2011-11-30 PerfektesChaos@de.wikipedia
      var i, k;
      var r  =  false;
      var re  =  false;
      var $g;
      if ( ! FAdm.ns.sCat ) {
         FAdm.ns.sCat  =  FAdm.ns.fetch( FAdm.ns.nCat );
      }
      if ( area ) {   // edit mode; wgCategories empty
         if ( FAdm.cat.reMaintain ) {
            re  =  "\\[\\[ *" + FAdm.ns.sCat + ": *"
                   + FAdm.cat.reMaintain + " *(\\||]])";
            re  =  new RegExp( re );
            r   =  re.test( area );
         }
      } else {
         $g  =  jQuery( FAdm.guide.selTemplate );
         if ( $g.length ) {
            r  =  true;
         } else {
            if ( ! FAdm.file.cats ) {
               FAdm.file.cats  =  mw.config.get( "wgCategories" );
            }
            FAdm.guide.furnish();
            if ( ! FAdm.cat.regexpMaintain ) {
               if ( FAdm.cat.reMaintain ) {
                  FAdm.cat.regexpMaintain  =
                                       new RegExp( FAdm.cat.reMaintain );
               }
            }
            for ( i = 0;  i < FAdm.file.cats.length;  i++ ) {
               k  =  FAdm.cat.family( FAdm.file.cats[i] );
               if ( k < 0 ) {
                  r  =  true;
                  break;   // for i
               }
            }   // for i
         }
      }
      return r;
   };   // .cat.fenced()



   FAdm.cat.file  =  function ( apply ) {
      // Is current page member of a file category?
      // Precondition:
      //    apply  -- string with content tail, orfalse if unknown
      //    Current page is a file description page
      // Postcondition:
      //    Returns true iff member of file category, maintenance ignored
      // Uses:
      //    >  .ns.nCat
      //    >  .cat.reMaintain
      //    >< .ns.sCat
      //    >< .str.action
      //    >< .cat.regexpMaintain
      //    >< .file.cats
      //    .ns.fetch()
      //    .cat.family()
      //    .edit.field()
      //    mw.config.get()
      // 2011-11-30 PerfektesChaos@de.wikipedia
      var i, k;
      var r  =  false;
      var re;
      var s;
      if ( ! FAdm.ns.sCat ) {
         FAdm.ns.sCat  =  FAdm.ns.fetch( FAdm.ns.nCat );
      }
      if ( ! FAdm.str.action ) {
         FAdm.str.action  =  mw.config.get( "wgAction" );
      }
      switch ( FAdm.str.action ) {
         case "view" :
            if ( ! FAdm.cat.regexpMaintain ) {
               if ( FAdm.cat.reMaintain ) {
                  FAdm.cat.regexpMaintain  =
                                       new RegExp( FAdm.cat.reMaintain );
               }
            }
            if ( ! FAdm.file.cats ) {
               FAdm.file.cats  =  mw.config.get( "wgCategories" );
            }
            for ( i = 0;  i < FAdm.file.cats.length;  i++ ) {
               k  =  FAdm.cat.family( FAdm.file.cats[i] );
               if ( k > 0 ) {
                  r  =  true;
                  break;   // for i
               }
            }   // for i
            break;
         case "edit" :
         case "submit" :
            if ( FAdm.cat.start ) {
               re  =  "\\[\\[ *" + FAdm.ns.sCat
                      + ": *" + FAdm.cat.start;
               if ( apply ) {
                  s  =  apply;
               } else {
                  s  =  FAdm.edit.field( false );
               }
               re  =  new RegExp( re );
               r   =  ( re.test( s ) );
            }
            break;
      }   // switch wgAction
      return r;
   };   // .cat.file()



   FAdm.cat.find  =  function () {
      // Make link controls for category page tools (deutsch)
      // Precondition:
      //    Current page displays file category
      // Postcondition:
      //    Link controls for tools are created
      // Uses:
      //    >  .wins.lot
      //    >  .wins.toolOut
      //    >< .cat.tools
      //    >< .str.page.title
      //    .wins.forwardMode()
      //    .portlet.factory()
      //    mw.config.get()
      //    mw.util.wikiUrlencode()
      // 2011-10-10 PerfektesChaos@de.wikipedia
      var s     =  "http://toolserver.org/~magnus/catscan_rewrite.php"
                   + "?language=de&ns%5B6%5D=1&doit=1&categories=";
      var tool  =  { target: false };
      if ( ! FAdm.str.page.title ) {
         FAdm.str.page.title  =  mw.config.get( "wgTitle" );
      }
      s  =  s  +  mw.util.wikiUrlencode( FAdm.str.page.title );
      FAdm.wins.forwardMode();
      if ( FAdm.wins.lot ) {
         tool.target  =  FAdm.wins.toolOut;
      }
      if ( ! this.tools ) {
         this.tools  =  [ false, false, false, false ];
      }
      tool.href      =  s + "&templates_no=Gepr%C3%BCfte+Datei";
      tool.title     =  "Ungeprüft";
      tool.id        =  "ca-filereview0";
      tool.hint      =  "Ungeprüfte Dateien";
      tool.hotkey    =  "0";
      this.tools[0]  =  FAdm.portlet.factory( tool );
      tool.href      =  s + "%0D%0ADatei%3AZweitpr%C3%BCfung+ausstehend";
      tool.title     =  "1x geprüft";
      tool.id        =  "ca-filereview1";
      tool.hint      =  "Erst einmal geprüfte Dateien";
      tool.hotkey    =  "1";
      this.tools[1]  =  FAdm.portlet.factory( tool );
      tool.href      =  s + "%0D%0ADatei%3Agepr%C3%BCfte+Datei";
      tool.title     =  "2x geprüft";
      tool.id        =  "ca-filereview2";
      tool.hint      =  "Zweimal geprüfte Dateien";
      tool.hotkey    =  "2";
      this.tools[2]  =  FAdm.portlet.factory( tool );
      tool.href      =  s + "&negcats=Datei%3ANoCommons";
      tool.title     =  "ohne NoCommons";
      tool.id        =  "ca-filereviewN";
      tool.hint      =  "Dateien ohne 'NoCommons'";
      tool.hotkey    =  "N";
      this.tools[3]  =  FAdm.portlet.factory( tool );
      /*
       Nach Einführung: Vorlagen-Box (weißes Dingsda) ausblenden?
       show= fileAdm.review.selTemplate + "{ display: none!important; }";
       mw.util.addCSS( show );
       */
   };   // .cat.find()



   FAdm.cat.flip  =  function () {
      // Divert window targets of category tool links
      // Postcondition:
      //    Link controls for tools are set to current target
      // Uses:
      //    >  .wins.lot
      //    >  .wins.toolOut
      //    >< .cat.tools
      // 2011-08-31 PerfektesChaos@de.wikipedia
      var domA;
      var i;
      if ( this.tools ) {
         for ( i = 0;  i < this.tools.length;  i++ ) {
            domA  =  this.tools[i].dom;
            if ( FAdm.wins.lot ) {
               domA.setAttribute( "target", FAdm.wins.toolOut );
            } else {
               domA.removeAttribute( "target" );
            }
         }   //  for i
      }
   };   // .cat.flip()



   FAdm.cat.format  =  function () {
      // Begin of editing file category page: insert or reformat template
      // Precondition:
      //    Page contains wpTextbox1
      // Postcondition:
      //    Page is formatted, template is in first line now
      // Uses:
      //    >  .cat.stamp
      //    >  .cat.reNoParSuggest
      //    >< .str.page.title
      //    .cat.fenced()
      //    .edit.field()
      //    .edit.formatPageTail()
      //    mw.config.get()
      // 2011-10-23 PerfektesChaos@de.wikipedia
      var got;
      var lazy;
      var lock;
      var re;
      var scope  =  FAdm.edit.field( false );
      var shift;
      var swap;
      if ( typeof( scope )  ===  "string" ) {
         lock   =  this.fenced( scope );
         lazy   =  lock;
         re     =  new RegExp( "({{ *"
                               + this.stamp
                               + " *(\\| *([^}]*))? *}} *\n?)",
                               "i" );
         shift  =  scope.replace( /\t/g, " " );
         swap   =  "{{" + this.stamp;
         got    =  re.exec( shift );
         if ( got !== null ) {
            if ( got[3] ) {
               swap  =  swap + "|" + got[3];
               lazy  =  true;
            }
            shift  =  shift.replace( re, "\n" );
         }
         if ( lock ) {
            swap  =  "";
         } else {
            swap  =  swap + "}}";
         }
         got    =  FAdm.edit.formatPageTail( shift );
         shift  =  got[0]
                   + ( got[0].length &&  got[1].length  ?  "\n\n"  :  "")
                   + got[1];
         shift  =  swap  +  ( shift.length ? "\n\n" : "" )  +  shift;
         if ( ! lazy ) {
            re  =  new RegExp( this.reNoParSuggest );
            if ( ! FAdm.str.page.title ) {
               FAdm.str.page.title  =  mw.config.get( "wgTitle" );
            }
            swap  =  FAdm.str.page.title.substr( this.start.length );
            if ( ! re.test( swap ) ) {
               shift  =  "{{" + this.stamp + "|"
                         + swap
                         + shift.substr( this.stamp.length + 2 );
            }
         }
         if ( shift !== scope ) {
            FAdm.edit.field( shift );
         }
      }
   };   // .cat.format()



};   // .bb.cat()
mediaWiki.libs.fileAdm.bb.cat( mediaWiki.libs.fileAdm, mediaWiki );
delete mediaWiki.libs.fileAdm.bb.cat;



//-----------------------------------------------------------------------



mediaWiki.libs.fileAdm.bb.edit  =  function ( FAdm ) {
   // Edit support
   // 2012-06-11 PerfektesChaos@de.wikipedia
   "use strict";
   if ( typeof FAdm.edit !== "object" ) {
      FAdm.edit  =  {  template: { }  };
   }
   if ( typeof FAdm.edit.template !== "object") {
      FAdm.edit.template  =  { };
   }



   FAdm.edit.fetchRegexp  =  function ( ask ) {
      // Fetch regexp for page title
      // Precondition:
      //    ask  -- regexp string for page title
      // Postcondition:
      //    Return regexp string for page title
      // 2014-06-05 PerfektesChaos@de.wikipedia
      var re0  =  new RegExp( "([.*+?(|){}\\^$\\x5B])", "g" ),
          re1  =  new RegExp( "_", "g" ),
          re2  =  new RegExp( " +", "g" ),
          re3  =  new RegExp( " ", "g" ),
          r    =  ask.replace( re0, "\\$1" ),
          s    =  r.substr( 0, 1 ),
          sL   =  s.toLowerCase(),
          sU   =  s.toUpperCase();
      r  =  r.replace( re1, " " )
             .replace( re2, " " )
             .replace( re3, "[ _]+" );
      if ( sL !== sU ) {
         r  =  "[" + sL + sU + "]" + r.substr( 1 );
      }
      return  r;
   };   // .edit.fetchRegexp()



   FAdm.edit.field  =  function ( alter ) {
      // Retrieve or replace wikitext using edit area
      // Precondition:
      //    Interactive mode (web form)
      //    alter  -- false or undefined:  Retrieve wikitext
      //              string:              Modified wikitext to be stored
      // Postcondition:
      //    Return  string:  wpTextbox1 content  if ! alter
      //            false:   if alter
      //                     if ! alter:  editform unavailable
      //                                  or area not modifiable
      // Uses:
      //    >  .ia
      //    >  .ia.editor
      //    >  .ia.$textarea
      //    >  .str.page.content
      //    .edit.form()
      //    "editform"
      //       >< .wpTextbox1
      //    WikEd
      //       >  wikEd.disabled
      //       wikEd.Setup()
      //       wikEd.UpdateTextarea()
      //       wikEd.UpdateFrame()
      // 2011-12-19 PerfektesChaos@de.wikipedia
      var r  =  false;
      if ( ! FAdm.ia ) {   // initialize
         this.form();
         if ( FAdm.ia ) {
            if ( typeof( window.wikEd )  ===  "object" ) {
               if ( window.wikEd !== null ) {
                  if ( typeof( window.wikEd.disabled ) !== "boolean" ) {
                     if ( typeof window.wikEd.Setup  ===  "function" ) {
                        window.wikEd.Setup();
                     }
                  }
                  if ( typeof( window.wikEd.disabled ) === "boolean" ) {
                     if ( ! window.wikEd.disabled ) {
                        FAdm.ia.editor  =  "wikEd";
                     }   // not wikEd.disabled
                  }   // wikEd.disabled boolean
               }   // != null
            }   // wikEd
         }   // ia
      }   // initialize
      if ( typeof( FAdm.ia )  ===  "object" ) {   // online
         if ( typeof( alter )  ===  "string" ) {   // replace
            FAdm.ia.$textarea.val( alter );
            switch ( FAdm.ia.editor ) {
               case "wikEd" :   // wikEd
                  window.wikEd.UpdateFrame( null );
                  break;
            }   // switch editor
         } else {   // retrieve
            switch ( FAdm.ia.editor ) {
               case "wikEd" :   // wikEd
                  window.wikEd.UpdateTextarea( null );
                  break;
            }   // switch kit
            FAdm.str.page.content  =  FAdm.ia.$textarea.val();
            r                      =  FAdm.str.page.content;
         }   // mode
      }   // online
      return r;
   };   // .edit.field()



   FAdm.edit.finalize  =  function ( after ) {
      // End (auto-)editing file description page, drop content/summary
      // Precondition:
      //    Page contains wpTextbox1
      //    after  --  false     -- nothing to do
      //               array[3]  -- modified
      //                    [0] body string
      //                    [1] summary; may be false if nothing done
      //                    [2] true: minor change
      //                    [3] (subject)
      //                    [4] watchlist behaviour
      // Postcondition:
      //    Page is formatted, templates are ahead of tail if appropriate
      // Uses:
      //    >  .str.page.content
      //    >  .ia.$editform
      //    .edit.field()
      //    .str.trimLeft()
      // 2011-10-24 PerfektesChaos@de.wikipedia
      var $field;
      var look;
      var looking;
      var setting;
      var summary;
      if ( after ) {
         FAdm.str.page.content  =  after[0];
         this.field( FAdm.str.page.content );
         $field  =  FAdm.ia.$editform.find( "#wpSummary" );
         if ( $field.length ) {
            summary  =  $field.val();
            if ( typeof( summary )  ===  "string" ) {
               summary  =  FAdm.str.trimLeft( summary );
            } else {
               summary  =  "";
            }
            if ( after[1] ) {
               if ( summary.length ) {
                  if ( summary.indexOf( after[1] )  <  0 ) {
                     if ( after[2] ) {
                        summary  =  summary + ", " + after[1];
                     } else {
                        summary  =  after[1] + ", " + summary;
                     }
                  }
               } else {
                  summary  =  after[1];
               }
            }
            $field.val( summary );
            if ( typeof( after[4] )  ===  "string" ) {
               setting  =  after[4];
               if ( setting === "watch" ) {
                  look  =  true;
               } else if ( setting === "unwatch" ) {
                  look  =  false;
               } else {
                  setting  =  false;
               }
               if ( setting ) {
                  $field  =  FAdm.ia.$editform.find( "#wpWatchthis" );
                  if ( $field.length ) {
                     looking  =  $field.prop( "checked" );
                     if ( looking !== look ) {
                        if ( look ) {
                           $field.attr( "checked" );
                        } else {
                           $field.attr( "checked", null );
                        }
                     }
                  }
               }
            }
         }
      }
   };   // .edit.finalize()



   FAdm.edit.find  =  function ( ask, apply ) {
      // Retrieve transclusion of template
      // Precondition:
      //    ask    -- core template name regexp
      //    apply  -- false, or page content string (not UTF-8)
      // Postcondition:
      //    Returns  Array[2]
      //                  [0] entire template
      //                  [1] remaining text body
      //             false, if not found
      // Uses:
      //    .edit.field()
      //    .edit.template.fetchRE()
      //    .str.trimLeft()
      //    .str.trimRight()
      // 2011-11-30 PerfektesChaos@de.wikipedia
      var got;
      var r    =  false;
      var re;
      var s;
      var see;
      see  =  ( apply  ?  apply  :  this.field( false ) );
      if ( see ) {
         re  =  this.template.fetchRE( ask, false ) + "[^}]*}}";
         re   =  new RegExp( re );
         got  =  re.exec( see );
         if ( got ) {
            s  =  see.replace( re, "" );
            s  =  FAdm.str.trimRight( FAdm.str.trimLeft( s ) );
            s  =  s.replace( /\n\n\n+/g, "\n\n" );
            r  =  [ got[0], s ];
         }
      }
      return r;
   };   // .edit.find()



   FAdm.edit.fold  =  function ( adjust, ask, assign, align ) {
      // Reformat template transclusion
      // Precondition:
      //    adjust  -- page content body string
      //    ask     -- template name
      //    assign  -- false: remove transclusion   true: Normalize
      //    align   -- true: order ahead of anything   false: at end
      // Postcondition:
      //    Return  false     -- no transclusion
      //            array[3]  -- modified
      //                 [0] adjusted content body string
      //                 [1] entire transclusion
      //                 [2] parameters from '|' until "}}";  or false
      //                 [3] content body without transclusion
      // Uses:
      //    .edit.template.fetchRE()
      //    .str.trimLeft()
      //    .str.trimRight()
      //    .edit.formatUserLink()
      // 2011-11-30 PerfektesChaos@de.wikipedia
      var got;
      var k;
      var n;
      var r      =  false;
      var re     =  "(" + this.template.fetchRE( ask, false ) + ")"
                    + "(\\|[ \t\n]*"
                    + "([^}]+:[^}]+({{!}})?[^}]+)*"
                    + ")*"
                    + "[ \t\n]*}}[ \t]*\n*";
      var shift;
      var story;
      var stub;
      var swap;
      re   =  new RegExp( re );
      got  =  re.exec( adjust );
      if ( got !== null ) {
         k      =  got[1].length;
         n      =  got[0].length;
         shift  =  adjust.substr( got.index, n );
         story  =  shift.substr( k );
         stub   =  adjust.substr( 0, got.index )
                   + adjust.substr( got.index + n );
         swap   =  false;
         swap  =  "{{" + ask;
         stub  =  FAdm.str.trimLeft( FAdm.str.trimRight( stub ) );
         if ( story.charCodeAt( 0 )  ===  124 ) {   // '|'
            story  =  FAdm.str.trimRight( story );
            story  =  story.substr( 0,  story.length - 2 );
            story  =  this.formatUserLink( story );
            swap   =  swap + story;
         } else {
            story  =  false;
         }
         swap  =  swap + "}}";
         if ( assign ) {
            if ( align ) {
               shift  =  swap + "\n\n" + stub;
            } else {
               shift  =  stub + "\n\n" + swap;
            }
         }
         r  =  [ shift, swap, story, stub ];
      }
      return r;
   };   // .edit.fold()



   FAdm.edit.form  =  function () {
      // Setup interactive editform object
      // Precondition:
      //    Interactive mode (web form)
      // Postcondition:
      //    Object constructed, if possible
      // Uses:
      //    >< .ia
      //     < .ia.$editform
      //     < .ia.$textarea
      //     < .ia.editor
      //    "editform"
      //       >  .wpTextbox1
      // 2011-10-10 PerfektesChaos@de.wikipedia
      var $box;
      var $form;
      if ( ! FAdm.ia ) {   // initialize
         $form  =  jQuery( "#editform" );
         if ( $form.length ) {   // editing
            $box  =  jQuery( "#wpTextbox1" );
            if ( $box.length ) {   // textarea
               if ( ! $box.attr( "readonly" ) ) {   // modifiable
                  FAdm.ia  =  { $editform: $form,
                                $textarea: $box,
                                editor:    false };
               }   // modifiable
            }   // textarea
         }   // editing
      }   // initialize
   };   // .edit.form()



   FAdm.edit.formatPageTail  =  function ( adjust ) {
      // Cleanup in tail region of some page: categories and interwiki
      // Precondition:
      //    adjust  -- page content string
      // Postcondition:
      //    Return  array[2]
      //            [0] body string
      //            [1] tail region: sort, categories, interwiki
      // Uses:
      //    >  .edit.defaultsort
      //    >  .ns.nCat
      //    >< .ns.sCat
      //     < .edit.sisters
      //    .str.trimLeft()
      //    .str.trimRight()
      //    .ns.fetch()
      //    (.edit.foundIW)
      // Requires: JavaScript 1.3   String.replace(regexp, function)
      // 2012-06-10 PerfektesChaos@de.wikipedia
      var got;
      var re;
      var seek   =  "Category";
      var start  =  FAdm.str.trimRight( FAdm.str.trimLeft( adjust ) );
      var swap   =  "";
      start  =  start.replace( /\t/g, " " );
      start  =  start.replace( /\{\{ +/g, "{{" );
      start  =  start.replace( /\[\[ +/g, "[[" );
      re     =  "{{(DEFAULTSORTKEY|DEFAULTCATEGORYSORT|DEFAULTSORT) *:";
      re     =  new RegExp( re, "gi" );
      start  =  start.replace( re, "{{DEFAULTSORT:" );
      re     =  " *{{(DEFAULTSORT";
      if ( this.defaultsort ) {
         if ( this.defaultsort !== "DEFAULTSORT" ) {
            re  =  re + "|" + this.defaultsort;
         }
      }
      re   =  re + ") *:([^}\n]*}}) *\n?";
      re   =  new RegExp( re, "i" );
      got  =  re.exec( start );
      if ( got !== null ) {
         swap   =  "{{" + this.defaultsort + ":" + got[2];
         start  =  start.replace( re, "" );
      }
      if ( ! FAdm.ns.sCat ) {
         FAdm.ns.sCat  =  FAdm.ns.fetch( FAdm.ns.nCat );
      }
      if ( FAdm.ns.sCat !== seek ) {
         seek  =  seek + "|" + FAdm.ns.sCat;
      }
      seek  =  "\\[\\[ *(" + seek + "): *(.+) *\\]\\] *\n?";
      re    =  new RegExp( seek, "i" );
      got   =  re.exec( start );
      while ( got ) {
         if ( swap ) {
            swap  =  swap + "\n";
         }
         swap   =  swap + "[[" + FAdm.ns.sCat + ":" + got[2] + "]]";
         start  =  start.substr( 0, got.index )  +
                   start.substr( got.index + got[0].length );
         got    =  re.exec( start );
      }   // while got
      swap               =  FAdm.str.trimRight( swap );
      FAdm.edit.sisters  =  "";
      re                 =  "\n? *\\[\\["
                            + "([a-z][a-z][-a-z]*)"
                            + ":"
                            + "([^|\n]+)"
                            + "\\]\\] *"
                            + "(\n)?";
      re                 =  new RegExp( re, "ig" );
      start              =  FAdm.str.trimRight( start );
      start              =  start.replace( re, this.foundIW );
      if ( FAdm.edit.sisters ) {
         swap   =  swap + "\n" + FAdm.edit.sisters;
         start  =  FAdm.str.trimRight( start );
      }
      start  =  start.replace( /\n +\n/g, "\n\n" );
      start  =  start.replace( /\n\n\n/g, "\n\n" );
      return  [ start, swap ];
   };   // .edit.formatPageTail()



   FAdm.edit.formatUserLink  =  function ( adjust ) {
      // Format first link to a user, if any
      // Precondition:
      //    adjust  -- string, may contain user identification
      // Postcondition:
      //    Returns string, may have re-formatted user links
      //                    at least first user link has canonical form
      //    User properties are defined
      // Uses:
      //    >  .ns.sUser
      //    .users.fair()
      //    .str.trimLeft()
      //    .str.trimRight()
      // 2013-08-25 PerfektesChaos@de.wikipedia
      var i, j, k, re, signed,
          story  =  FAdm.users.fair( adjust ),
          start  =  "[[" + FAdm.ns.sUser + ":";
      re     =  new RegExp( "(\\[\\[" + FAdm.ns.sUser + ":[^{[]+){{!}}",
                            "g" );
      story  =  story.replace( re, "$1|" );
      k      =  story.indexOf( start );
      if ( k >= 0 ) {
         k  +=  start.length;
         i   =  story.indexOf( "|", k );
         j   =  story.indexOf( "]]", k );
         if ( j > k ) {
            start   =  story.substr( 0, k );
            j       =  ( i > k  &&  i < j   ?   i   :   j   );
            signed  =  story.slice( k, j );
            story   =  story.substr( j );
            signed  =  FAdm.str.trimRight( FAdm.str.trimLeft( signed ) );
            signed  =  decodeURIComponent( signed );
            story   =  start + signed + story;
         }
      }
   return story;
   };   // .edit.formatUserLink()



   FAdm.edit.foundIW  =  function ( all, aim, assign, after ) {
      // Analyse possible interwiki link
      // Precondition:
      //    all     -- entire string including possible prolog / epilog
      //    aim     -- submatch [1]: possible sister project
      //    assign  -- submatch [2]: title on aim
      //    after   -- submatch [3]: trailing line break, or null
      // Postcondition:
      //    Return unchanged string, or empty string if interwiki
      // Uses:
      //    >< .edit.sisters
      //    .lang.flop()
      //    .str.trimLeft()
      //    .str.trimRight()
      // Remark: Used as event handler -- 'this' is not FAdm.edit
      // 2012-06-10 PerfektesChaos@de.wikipedia
      var r  =  all;
      var s;
      //    RegExp was used.
      if ( ! FAdm.lang.flop( aim ) ) {
         if ( assign.indexOf( "]" )  <  0 ) {
            s  =  FAdm.str.trimRight( FAdm.str.trimLeft( assign ) );
            if ( s ) {
               FAdm.edit.sisters  =  FAdm.edit.sisters + "\n"
                                     + "[[" + aim.toLowerCase() + ":" + s
                                     + "]]";
               r                  =  ( after ? "\n" : "" );
            }
         }
      }
      return r;
   };   // .edit.foundIW()



   FAdm.edit.template.fetchParameter  =  function ( achieve, access ) {
      // Fetch parameter from template transclusion
      // Precondition:
      //    achieve  -- string with template transclusion
      //    access   -- number of parameter or string with name
      // Postcondition:
      //    Return trimmed string for parameter value, or false
      // Uses:
      //    .str.trimLeft()
      //    .str.trimRight()
      // 2011-10-11 PerfektesChaos@de.wikipedia
      var got;
      var r    =  false;
      var re   =  "\\|[ \t\n]*" + access + "[ \t\n]*=([^|}]*)[|}]";
      re   =  new RegExp( re );
      got  =  re.exec( achieve );
      if ( got === null ) {
         if ( typeof( access )  ===  "number" ) {
            got  =  achieve.split( "|" );
            if ( got.length >= access ) {
               r  =  got[access];
               if ( typeof( r )  ===  "string" ) {
                  r  =  r.replace( /\}\}$/, "" );
               }
            }
         }
      } else {
         r  =  got[1];
      }
      if ( typeof( r )  ===  "string" ) {
         r  =  FAdm.str.trimRight( FAdm.str.trimLeft( r ) );
      }
      return r;
   };   // .edit.template.fetchParameter()



   FAdm.edit.template.fetchRE  =  function ( ask, around ) {
      // Fetch regexp for template transclusion
      // Precondition:
      //    ask     -- template name (trimmed)
      //    around  -- include pipe or }}
      // Postcondition:
      //    Return regexp string for template transclusion head
      // Uses:
      //    >  .ns.nTemplate
      //    >< .ns.sTemplate
      //    >< .ns.reTemplate
      //    .edit.fetchRegexp()
      //    .ns.fetch()
      // Requires: JavaScript 1.5   non-capturing parentheses
      // 2011-11-30 PerfektesChaos@de.wikipedia
      var i;
      var r;
      var s;
      if ( typeof( ask )  ===  "object" ) {
         r  =  "(";
         for ( i = 0;  i < ask.length;  i++ ) {
            r  =  r  +  ( i ? "|" : "" )
                  +  FAdm.edit.fetchRegexp( ask[i] );
         }   // for i
         r  =  r + ")";
      } else {
         r  =  FAdm.edit.fetchRegexp( ask );
      }
      if ( ! FAdm.ns.reTemplate ) {
         if ( ! FAdm.ns.sTemplate ) {
            FAdm.ns.sTemplate  =  FAdm.ns.fetch( FAdm.ns.nTemplate );
         }
         if ( FAdm.ns.sTemplate.toLowerCase() === "template" ) {
            FAdm.ns.reTemplate  =  "[tT]emplate";
         } else {
            s                   =  FAdm.ns.sTemplate.substr( 0, 1 );
            FAdm.ns.reTemplate  =  "(?:[tT]emplate|["
                                   + s.toLowerCase() + s.toUpperCase()
                                   + "]"
                                   + FAdm.ns.sTemplate.substr( 1 ) + ")";
         }
      }
      r  =  "{{[ \t\n]*"
            + "(?:" + FAdm.ns.reTemplate + ":[ \t\n]*)?" + r;
      r  =  r + "[ \t\n]*";
      if ( around ) {
         r  =  r + "(?:}}|\\|)";
      }
      return  r;
   };   // .edit.template.fetchRE()



};   // .bb.edit()
mediaWiki.libs.fileAdm.bb.edit( mediaWiki.libs.fileAdm );
delete mediaWiki.libs.fileAdm.bb.edit;



//-----------------------------------------------------------------------



mediaWiki.libs.fileAdm.bb.file  =  function ( FAdm, mw ) {
   // File description page support
   // 2012-06-11 PerfektesChaos@de.wikipedia
   "use strict";
   if ( typeof FAdm.file !== "object" ) {
      FAdm.file  =  { };
   }



   FAdm.file.action  =  function () {
      // Open single file description page
      // Precondition:
      //    Page is supposed to be a local single file description page
      //    Description is not just a copy from Commons
      //    window.document is ready
      // Postcondition:
      //    Basic procedures are performed.
      //    Advanced procedures are triggered.
      //    Returns void(0), as required in GUI action, if browser window
      // Uses:
      //    >  .file.type
      //    >  .users.r
      //    >  .review.features
      //    >  .users.t
      //    >  .trans.features
      //    >  .queer.stamp
      //    >  .queer.stampNotified
      //    >  .queer.link
      //    >  .trans.stamp
      //    >< .str.action
      //    >< .file.cats
      //    .guide.furnish()
      //    .guide.fancy()
      //    .queer.fetch()
      //    .edit.field()
      //    .edit.find()
      //    .trans.bot.find()
      //    .users.fidelity()
      //    .file.foreign()
      //    .file.first()
      //    .users.friend()
      //    .queer.features()
      //    .review.features()
      //    .portlet.factory()
      //    (.review.features)
      //    (.trans.features)
      //    (.queer.features)
      //    mw.config.get()
      //    mw.util.getParamValue()
      // Remark: Used as event handler -- 'this' is not FAdm.file
      // 2012-01-10 PerfektesChaos@de.wikipedia
      var further  =  false;
      var insider  =  -2;
      var label    =  false;
      var later    =  false;
      var lazy;
      var legal    =  true;
      var live     =  false;
      var lock     =  true;
      var sub      =  false;
      var select;
      var spool;
      var story;
      var template;
      if ( ! FAdm.str.action ) {
         FAdm.str.action  =  mw.config.get( "wgAction" );
      }
      switch ( FAdm.str.action ) {
         case "view" :
            if ( !  mw.util.getParamValue("diff") ) {
               label  =  true;
            }
            break;
         case "submit" :
            later  =  true;
            // fall through
         case "edit" : //
            live  =  true;
            break;
         default :
            lock  =  false;
      }   // switch wgAction
      if ( label ) {
         if ( ! FAdm.file.cats ) {
            FAdm.file.cats  =  mw.config.get( "wgCategories" );
         }
         FAdm.guide.furnish();
         FAdm.guide.fancy( FAdm.file.cats, false );
         sub  =  FAdm.file.type.substr( 0, 1 ).toUpperCase();
         switch ( sub ) {
            case "C" :
               if ( FAdm.file.type !== "category" ) {
                  further  =  FAdm.queer.features;
                  insider  =  0;
                  legal    =  true;
                  lock     =  false;
                  FAdm.queer.fetch( 1, false );
               }
               break;
            case "R" :
               if ( ! FAdm.trans.flop( false ) ) {
                  insider  =  FAdm.users.r;
                  further  =  FAdm.review.features;
               }
               break;
            case "F" :
            case "T" :
               if ( FAdm.users.fidelity() ) {
                  insider  =  0;
                  legal    =  true;
               } else {
                  insider  =  FAdm.users.t;
                  legal    =  false;
               }
               further  =  FAdm.trans.features;
               break;
         }   // switch sub
      }
      if ( live ) {
         lazy    =  false;
         select  =  false;
         spool   =  false;
         story   =  false;
         spool   =  mw.util.getParamValue( "fileAdm" );
         if ( typeof( spool )  ===  "string" ) {
            if ( spool.indexOf( "questionable" )  ===  0 ) {
               FAdm.queer.fetch( 2, spool );
               select  =  spool;
               lazy    =  true;
               lock    =  false;
            } else if ( spool === "approve" ) {
               select  =  spool;
            }
         } else {
            spool  =  false;
         }
         if ( ! lazy ) {
            story     =  FAdm.edit.field( false );
            template  =  FAdm.edit.find( FAdm.queer.stamp, story );
            if ( template ) {
               FAdm.queer.fetch( 3, template[0] );
               lock  =  false;
            }
         }
         template  =  FAdm.edit.find( FAdm.queer.stampNotified, story );
         if ( template ) {
            FAdm.queer.fetch( 4, template[0] );
            lock  =  false;
         }
         if ( lock ) {
            if ( FAdm.users.fidelity() ) {
               FAdm.trans.bot.find( true, false );
            } else {
               FAdm.users.friend( "T",
                                  FAdm.users.t,
                                  FAdm.trans.bot.find );
            }
            if ( ! select ) {
               if ( spool ) {
                  select  =  spool;
                  sub     =  true;
               } else if ( FAdm.edit.find( FAdm.trans.stamp, story ) ) {
                  sub  =  true;
               }
               if ( ! sub ) {
                  if ( ! FAdm.file.foreign() ) {
                     insider  =  FAdm.users.r;
                     further  =  FAdm.review.features;
                     sub      =  "R";
                  }
               }
            }
         } else {
            further  =  FAdm.queer.features;
            insider  =  0;
            label    =  true;
            legal    =  true;
         }
         FAdm.file.first( select );
      }
      if ( further ) {
         if ( insider ) {
            if ( insider > 0 ) {
               FAdm.users.friend( sub, insider, further );
            }
         } else if ( label ) {
            further( legal, true );
         }
      }
      if ( lock ) {
         FAdm.queer.link.click  =  "queer.features(true,true)";
         FAdm.queer.link.id     =  "ca-queer";
         FAdm.portlet.factory( FAdm.queer.link );
      }
      return void(0);
   };   // .file.action()



   FAdm.file.fire  =  function ( action ) {
      // Start editing of file description page
      // Precondition:
      //    action  -- URL parameter for edit
      // Uses:
      //    >< .str.page.urlEnc
      //    >< .str.page.name
      //    mw.util.getParamValue()
      //    mw.config.get()
      //    mw.util.wikiUrlencode()
      //    mw.util.wikiScript()
      // Remark: Used as event handler -- 'this' is not FAdm.file
      // 2011-10-11 PerfektesChaos@de.wikipedia
      var skin   =  mw.util.getParamValue( "useskin" );
      var start  =  mw.config.get( "wgServer" )  +
                    mw.config.get( "wgScript" )  +  "?title=";
      if ( ! FAdm.str.page.urlEnc ) {
         if ( ! FAdm.str.page.name ) {
            FAdm.str.page.name  =  mw.config.get( "wgPageName" );
         }
         FAdm.str.page.urlEnc  =
                             mw.util.wikiUrlencode( FAdm.str.page.name );
      }
      start  =  start + FAdm.str.page.urlEnc
                + "&action=edit&fileAdm=" + action;
      if ( skin ) {
         start  =  start + "&useskin=" + skin;
      }
      document.location.href  =  start;
   };   // .file.fire()



   FAdm.file.first  =  function ( action ) {
      // Begin of file description page edit
      // Precondition:
      //    Page contains wpTextbox1
      //    action  -- false: just edit   string: keyword list
      //                                          "approve", "transfer",
      //                                          "questionable.*"
      // Postcondition:
      //    Page is formatted, templates are ahead of tail if appropriate
      // Uses:
      //    >  .ia.$editform
      //    .edit.field()
      //    .review.format()
      //    .trans.format()
      //    .queer.format()
      //    .file.format()
      //    .edit.finalize()
      // Remark: Used as event handler -- 'this' is not FAdm.file
      // 2013-01-11 PerfektesChaos@de.wikipedia
      var change;
      var lazy;
      var s;
      FAdm.edit.field( false );
      if ( typeof( FAdm.str.page.content )  ===  "string" ) {
         change  =  false;
         lazy    =  true;
         switch ( action ) {
            case false :
               break;
            case "approve" :
               change  =  FAdm.review.format( FAdm.str.page.content,
                                              true );
               lazy    =  false;
               break;
            case "transfer" :
               change  =  FAdm.trans.format( true );
               lazy    =  false;
               break;
            default :
               if ( typeof( action )  ===  "string" ) {
                  if ( action.indexOf( "questionable" )  ===  0 ) {
                     s       =  action.substr( 12 );
                     change  =  FAdm.queer.format( FAdm.str.page.content,
                                                   ( s ? s : true ) );
                     lazy    =  false;
                  }
               }
         }   // switch action
         if ( lazy ) {
            change  =  FAdm.file.format( FAdm.str.page.content );
         }
         FAdm.edit.finalize( change );
      }
   };   // .file.first()



   FAdm.file.foreign  =  function () {
      // Is file described on Commons or supposed to be transferred?
      // Precondition:
      //    Any page is visible.
      //    window.document is ready
      // Postcondition:
      //    true iff there is a hint for a file Commons detected
      // Uses:
      //    >  .file.selCommons
      //    >  .file.selNowCommons
      // 2011-10-10 PerfektesChaos@de.wikipedia
      var r;
      var $elem  =  jQuery( this.selCommons );
      r  =  ( $elem.length > 0 );
      if ( ! r ) {
         $elem  =  jQuery( this.selNowCommons );
         r  =  ( $elem.length > 0 );
      }
      return r;
   };   // .file.foreign()



   FAdm.file.forge  =  function ( arglist ) {
      // Create jQuery standard form box on top of file description page
      // Precondition:
      //    arglist  -- object with definition
      //                >  .id       -- box identifier
      //                >  .shift    -- link title for batch/edit
      //                >  .soft     -- link title for start editing
      //                >  .splash   -- method call for edit in process
      //                >  .start    -- method call for editing by URL
      //                >  .style    -- box decoration
      //                >  .subject  -- box headline
      //                >  .submit   -- method call for batch
      // Postcondition:
      //    arglist modified
      //             < .$box      -- jQuery box if created
      //             < .$content  -- jQuery <div> for content region
      // Uses:
      //    >  .str.call
      //    >  .batch.styleButton
      //    >< .str.action
      //     < .file.mode
      //    mw.config.get()
      // 2013-01-07 PerfektesChaos@de.wikipedia
      var suite;
      var submit;
      var $button;
      var $flash;
      var $head;
      var $itemEdit;
      var $linkEdit;
      var $ul;
      arglist.$box  =  jQuery( "<div />" );
      if ( arglist.$box ) {
         if ( typeof( arglist.id )  ===  "string" ) {
            arglist.$box.attr( "id", arglist.id );
         }
         if ( typeof( arglist.style )  ===  "string" ) {
            arglist.$box.attr( "style", arglist.style );
         }
         if ( typeof( arglist.subject )  ===  "string" ) {
            $head  =  jQuery( "<strong />" );
            $head.text( arglist.subject );
            arglist.$box.append( $head );
         }
         arglist.$content  =  jQuery( "<div />" );
         arglist.$box.append( arglist.$content );
         if ( ! FAdm.str.action ) {
            FAdm.str.action  =  mw.config.get( "wgAction" );
         }
         if ( typeof( arglist.start )  ===  "string"   &&
              typeof( arglist.shift )  ===  "string" ) {
            switch ( FAdm.str.action ) {
               case "view" :
                  FAdm.file.mode  =  1;
                  break;
               case "edit" :
               case "submit" :
                  FAdm.file.mode  =  2;
                  break;
               default:
                  FAdm.file.mode  =  0;
            }   // switch wgAction
         }
         if ( FAdm.file.mode ) {
            suite  =  false;
            $linkEdit   =  jQuery( "<a />" );
            $button     =  false;
            if ( FAdm.file.mode === 1 ) {
               if ( typeof( arglist.soft )  ===  "string" ) {
                  suite  =  arglist.start;
                  $linkEdit.text( arglist.soft );
               }
               if ( typeof( arglist.submit )  ===  "string" ) {
                  submit  =  FAdm.str.call + arglist.submit
                             + ";void(0);";
                  $flash  =  jQuery( "<a />" );
                  $flash.text( arglist.shift );
                  $flash.attr( "href", submit );
                  $flash.attr( "style", FAdm.batch.styleButton );
                  $button  =  jQuery( "<p />" );
                  $button.append( $flash );
               }
            } else if ( FAdm.file.mode === 2 ) {
               suite  =  arglist.splash;
               $linkEdit.text( arglist.shift );
            }
            if ( suite ) {
               $ul        =  jQuery( "<ul />" );
               $itemEdit  =  jQuery( "<li />" );
               $linkEdit.attr( "href",
                               FAdm.str.call + suite + ";void(0);" );
               $itemEdit.append( $linkEdit );
               $ul.append( $itemEdit );
               arglist.$box.append( $ul );
            }
            if ( $button ) {
               arglist.$box.append( $button );
            }
         }
      }
   };   // .file.forge()



   FAdm.file.format  =  function ( adjust ) {
      // Reformat file description page
      // Precondition:
      //    adjust   -- page content string
      // Postcondition:
      //    Return  false     -- nothing done
      //            array[3]  -- modified
      //                 [0] body string
      //                 [1] summary; may be false if nothing done
      //                 [2] true: minor change
      // Uses:
      //    >  .file.replace
      //    >  .review.stamp
      //    >  .edit.summary0
      //    .edit.formatPageTail()
      //    .edit.fold()
      //    .str.trimRight()
      // 2012-08-30 PerfektesChaos@de.wikipedia
      var got;
      var i;
      var r        =  false;
      var shift;
      var start;
      var summary;
      got    =  FAdm.edit.formatPageTail( adjust );
      shift  =  got[1];
      start  =  got[0];
      if ( FAdm.file.replace ) {
         for ( i = 0;  i < FAdm.file.replace.length;  i++ ) {
            if ( typeof( FAdm.file.replace[i][0] ) === "string" ) {
               FAdm.file.replace[i][0]
                                  =  new RegExp( FAdm.file.replace[i][0],
                                                 "g" );
            }
            start  =  start.replace( FAdm.file.replace[i][0],
                                     FAdm.file.replace[i][1] );
         }   // for i
      }
      got  =  FAdm.edit.fold( start, FAdm.review.stamp, true, false );
      if ( got ) {
         start  =  got[0];
      }
      if ( start.length && shift.length ) {
         start  =  start + "\n\n";
      }
      shift  =  start + shift + "\n";
      if ( shift !== adjust ) {
         summary  =  false;
         if ( FAdm.str.trimRight( shift )  !==
              FAdm.str.trimRight( adjust ) ) {
            summary  =  FAdm.edit.summary0;
         }
         r  =  [ shift, summary, true ];
      }
      return r;
   };   // .file.format()



};   // .bb.file()
mediaWiki.libs.fileAdm.bb.file( mediaWiki.libs.fileAdm, mediaWiki );
delete mediaWiki.libs.fileAdm.bb.file;



//-----------------------------------------------------------------------



mediaWiki.libs.fileAdm.bb.guide  =  function ( FAdm, mw, $ ) {
   // File description page support
   // 2012-09-02 PerfektesChaos@de.wikipedia
   "use strict";
   if ( typeof FAdm.guide !== "object" ) {
      FAdm.guide  =  {  xClm: { }  };
   }
   if ( typeof FAdm.guide.xClm !== "object" ) {
      FAdm.guide.xClm  =  { };
   }



   FAdm.guide.action  =  function () {
      // Special view on some pages
      // Precondition:
      //    Page is supposed to be a view listing file description links
      //    window.document is ready
      // Postcondition:
      //    Images won't be displayed if not requested.
      //    Image toggle link is displayed.
      //    Procedures are performed.
      //    Returns void(0), as required in GUI action, if browser window
      // Uses:
      //    >  .ns.is
      //    >  .ns.nSpecial
      //    >  .ns.nProject
      //    >  .ns.nOthers1
      //    >  .opt.page.id
      //    >  .guide.selTemplate
      //    >< .misc.pageid
      //    .opt.page.form()
      //    .guide.fill()
      //    mw.config.get()
      //    jQuery()
      // Remark: Used as event handler -- 'this' is not FAdm.guide
      // 2011-09-08 PerfektesChaos@de.wikipedia
      var $guide;
      var listed  =  false;
      switch ( FAdm.ns.is ) {
         case FAdm.ns.nSpecial :
            listed  =  true;
            break;
         case FAdm.ns.nProject :
            if ( typeof( FAdm.misc.pageid )  !==  "number" ) {
               FAdm.misc.pageid  =  mw.config.get( "wgArticleId" );
            }
            if ( FAdm.misc.pageid === FAdm.opt.page.id ) {
               FAdm.opt.page.form();
               break;
            }
            // fall through
         case FAdm.ns.nOthers1 : //
//       case ns.nUser :
            $guide  =  jQuery( FAdm.guide.selTemplate );
            listed  =  ( $guide.length > 0 );
            break;
      }   // switch wgNamespaceNumber
      if ( listed ) {
         FAdm.guide.fill();
      }
      return void(0);
   };   // .guide.action()



   FAdm.guide.fancy  =  function ( assigned, adhere ) {
      // Detect appropriate style for file decoration
      // Precondition:
      //    assigned  -- categories of file, Array
      //    adhere    -- true: category is placed at assigned[].title
      //                 false: namespace 'category:' is not heading
      // Postcondition:
      //    Returns Array[2] with classification info
      //                 [0] classification string
      //                 [1] style string
      // Uses:
      //    >  .ns.nCat
      //    >  .guide.cats
      //    >  .guide.cats.none
      //    >  .guide.cats.checking
      //    >  .guide.cats.checkX
      //    >  .guide.cats.review0
      //    >  .guide.cats.review1
      //    >  .guide.cats.review2
      //    >  .guide.cats.license
      //    >  .guide.cats.transmit
      //    >  .guide.cats.transfer
      //    >  .guide.cats.transit
      //    >  .guide.cats.transfix
      //    >  .guide.cats.trash
      //    >  .guide.cats.transnot
      //    >< .ns.sCat
      //     < .file.type
      //    .ns.fetch()
      //    .guide.fulfil()
      // 2011-09-19 PerfektesChaos@de.wikipedia
      var gcs       =  FAdm.guide.cats;
      var i;
      var license   =  false;
      var r         =  [ "unknown", gcs.none ];
      var s;
      var shift     =  false;
      var shifting  =  false;
      var snow      =  false;
      var stack     =  false;
      var start     =  false;
      var stuck     =  false;
      var succeed1  =  false;
      var succeed2  =  false;
      var suspect   =  false;
      var swap      =  false;
      if ( ! adhere ) {
         if ( ! FAdm.ns.sCat ) {
            FAdm.ns.sCat  =  FAdm.ns.fetch( FAdm.ns.nCat );
         }
         start  =  FAdm.ns.sCat + ":";
      }
      for ( i = 0;  i < assigned.length;  i++ ) {
         s  =  assigned[i];
         if ( adhere ) {
            s  =  s.title;
         } else {
            s  =  start + s;
         }
         if ( ! license ) {
            license  =  FAdm.guide.fulfil( s, gcs.license );
         }
         if ( ! suspect ) {
            suspect  =  FAdm.guide.fulfil( s, gcs.checking );
         }
         if ( ! suspect ) {
            if ( ! shift ) {
               shift  =  FAdm.guide.fulfil( s, gcs.transfer );
            }
            if ( ! shifting ) {
               shifting  =  FAdm.guide.fulfil( s, gcs.transfix );
            }
            if ( ! snow ) {
               snow  =  FAdm.guide.fulfil( s, gcs.trash );
            }
            if ( ! stack ) {
               stack  =  FAdm.guide.fulfil( s, gcs.transmit );
            }
            if ( ! swap ) {
               swap  =  FAdm.guide.fulfil( s, gcs.transit );
            }
            if ( ! stuck ) {
               stuck  =  FAdm.guide.fulfil( s, gcs.review0 );
            }
            if ( ! ( succeed1 || succeed2 ) ) {
               succeed1  =  FAdm.guide.fulfil( s, gcs.review1 );
               succeed2  =  FAdm.guide.fulfil( s, gcs.review2 );
            }
         }
      }   // for i
      if ( suspect ) {
         if ( license ) {
            r  =  [ "checkX", gcs.checkX ];
         } else {
            r  =  [ "checking", suspect ];
         }
      } else if ( stuck || succeed1 || succeed2 ) {
         if ( snow ) {
            r  =  [ "trash", snow ];
         } else if ( shifting || stack || swap ) {
            r  =  [ "transnot", gcs.transnot ];
         } else if ( succeed2 ) {
            r  =  [ "review2", succeed2 ];
         } else if ( succeed1 ) {
            r  =  [ "review1", succeed1 ];
         } else {
            r  =  [ "review0", stuck ];
         }
      } else if ( license ) {
         if ( shift || shifting || snow || stack || swap ) {
            if ( snow ) {
               r  =  [ "trash", snow ];
            } else if ( shifting ) {
               r  =  [ "transfix", shifting ];
            } else if ( swap ) {
               r  =  [ "transit", swap ];
            } else {
               r  =  [ "transfer", shift ];
            }
         } else {
            r  =  [ "free", gcs.license[2] ];
         }
      }
      FAdm.file.type  =  r[0];
      return r;
   };   // .guide.fancy()



   FAdm.guide.fetch  =  function ( event, XMLHttpRequest, ajaxOptions ) {
      // Perform API request for state of all file links
      // Precondition:
      //    Parameters are ignored but may be evaluated
      //    Page is supposed to be a view on a guiding page
      // Postcondition:
      //    Self-callback after completion of first request
      // Uses:
      //    >  .ns.nFile
      //    >  .guide.multiQuery
      //    >  .batch.maxTitles
      //    >< .ns.sFile
      //    >< .str.artPath
      //    >< .guide.stateQuery
      //    >< .guide.stateIndex
      //    >< .guide.jumpQuery
      //    >< .batch.api
      //    >< .batch.reBlacklist
      //     < .guide.stateFilter
      //     < .guide.stateMax
      //     < .guide.stateMin
      //    .ns.fetch()
      //    jQuery().ajaxError()
      //    jQuery.getJSON()
      //    (.batch.failure)
      //    (.guide.found)
      //    (.guide.fetch)
      //    mw.config.get()
      // Remark: Used as event handler -- 'this' is not FAdm.guide
      // 2012-02-22 PerfektesChaos@de.wikipedia
      var k;
      var m;
      var n;
      var s;
      var set;
      if ( ! FAdm.guide.stateQuery ) {
         if ( ! FAdm.ns.sFile ) {
            FAdm.ns.sFile  =  FAdm.ns.fetch( FAdm.ns.nFile );
         }
         if ( ! FAdm.str.artPath ) {
            FAdm.str.artPath  =  mw.config.get( "wgArticlePath" );
            FAdm.str.artPath  =  FAdm.str.artPath.replace( /\$1/, "" );
         }
         FAdm.guide.stateFilter  =  FAdm.str.artPath
                                                   + FAdm.ns.sFile + ":";
         FAdm.guide.stateQuery   =  { action:       "query",
                                      prop:         "categories",
                                      cllimit:      500,
                                      indexpageids: true,
                                      format:       "json",
                                      titles:       false };
         FAdm.guide.stateIndex   =  0;
         FAdm.guide.jumpQuery    =  FAdm.guide.multiQuery;
         if ( ! FAdm.batch.api ) {
            FAdm.batch.api  =  mw.util.wikiScript( "api" );
         }
         if ( typeof( FAdm.batch.reBlacklist )  ===  "string" ) {
            FAdm.batch.reBlacklist  =
                          new RegExp( "(" + FAdm.batch.reBlacklist + ")",
                                      "gi" );
         }
         jQuery( document ).ajaxError( FAdm.batch.failure );
      }
      if ( FAdm.guide.stateIndex >= document.links.length ) {
         FAdm.guide.stateIndex  =  0;
         FAdm.guide.jumpQuery   =  FAdm.guide.multiQuery;
         if ( FAdm.guide.xClm.live ) {
            FAdm.guide.xClm.portlet.removeAttribute( "style" );
            FAdm.guide.xClm.live  =  false;
         }
      } else {
         m    =  0;
         n    =  FAdm.str.artPath.length;
         set  =  false;
         if ( FAdm.guide.jumpQuery >  FAdm.batch.maxTitles ) {
            FAdm.guide.jumpQuery  =  FAdm.batch.maxTitles;
         }
         for ( true;
               FAdm.guide.stateIndex < document.links.length;
               FAdm.guide.stateIndex++ ) {
            s  =  document.links[ FAdm.guide.stateIndex ].pathname;
            k  =  s.indexOf( FAdm.guide.stateFilter );
            if ( k >= 0 ) {
               FAdm.guide.stateIndex++;   // skip first link of img pair
               s  =  decodeURIComponent( s.substr( n ) );
               s  =  s.replace( FAdm.batch.reBlacklist, ".BLACKLIST." );
               if ( set ) {
                  set  =  set + "|" + s;
               } else {
                  set             =  s;
                  FAdm.guide.stateMin  =  FAdm.guide.stateIndex;
               }
               m++;
               if ( m === FAdm.guide.jumpQuery ) {
                  break;   // for stateIndex
               }
            }
         }   // for stateIndex
         if ( set ) {
            FAdm.guide.stateQuery.titles  =  set;
            if ( FAdm.guide.stateIndex < document.links.length ) {
               FAdm.guide.stateIndex++;
            }
            FAdm.guide.stateMax  =  FAdm.guide.stateIndex;
            jQuery.getJSON( FAdm.batch.api,
                            FAdm.guide.stateQuery,
                            FAdm.guide.found );
         }
         FAdm.guide.jumpQuery  +=  FAdm.guide.jumpQuery;
      }
   };   // .guide.fetch()



   FAdm.guide.fill  =  function () {
      // Decorate guiding page
      // Precondition:
      //    Page is supposed to be a view listing file description links
      //    window.document is ready
      // Postcondition:
      //    Images might be not yet displayed
      //    Image toggle link is displayed
      //    Procedures are performed
      // Uses:
      //    >  .guide.toggleImg
      //    >  .guide.$mins
      //    >  .guide.linkState
      //    >  .opt.lessMini
      //    >  .guide.toggleTgt
      //    >  .wins.lot
      //    >  .ns.is
      //    >  .str.page.scp
      //    >< .guide.lessMini
      //     < .guide.toggleImg.name
      //     < .guide.toggleImg.script
      //     < .guide.linkState.click
      //     < .guide.linkState.id
      //     < .guide.toggleTgt.name
      //     < .guide.toggleTgt.script
      //     < .guide.xClm.click
      //     < .guide.xClm.id
      //     < .guide.xClm.live
      //    .opt.factory()
      //    .opt.fetch()
      //    .guide.flipImage()
      //    .portlet.factory()
      //    .wins.forwardSingle()
      //    (.guide.flipImage)
      //    (.guide.flipTarget)
      // 2011-12-31 PerfektesChaos@de.wikipedia
      var elem;
      FAdm.guide.toggleImg.name    =  "MinImg";
      FAdm.guide.toggleImg.script  =  "guide.flipImage";
      if ( FAdm.opt.factory( FAdm.guide.toggleImg ) ) {
         FAdm.guide.lessMini  =  FAdm.opt.fetch( FAdm.opt.lessMini );
         FAdm.guide.flipImage( FAdm.guide.lessMini );
         if ( FAdm.guide.$mins.length ) {
            FAdm.guide.linkState.click  =  "guide.fetch()";
            FAdm.guide.linkState.id     =  "ca-guide-state";
            FAdm.portlet.factory( FAdm.guide.linkState );
            FAdm.guide.toggleTgt.name    =  "TgtWin";
            FAdm.guide.toggleTgt.script  =  "guide.flipTarget";
            if ( FAdm.opt.factory( FAdm.guide.toggleTgt ) ) {
               FAdm.portlet.flip( FAdm.guide.toggleTgt, FAdm.wins.lot );
            }
            FAdm.wins.forwardSingle();
            if ( FAdm.ns.is === -1 ) {
               if ( FAdm.str.page.scp ===  "Listfiles" ) {
                  FAdm.guide.xClm.click  =  "guide.xClm.fill(true)";
                  FAdm.guide.xClm.id     =  "ca-guide-column";
                  elem  =  FAdm.portlet.factory( FAdm.guide.xClm );
                  if ( elem ) {
                     FAdm.guide.xClm.portlet.setAttribute( "style",
                                                           "display:"
                                                           + "none" );
                     FAdm.guide.xClm.live  =  true;
                  }
               }
            }
         }
      }
   };   // .guide.fill()



   FAdm.guide.flag  =  function ( about, apply, assign ) {
      // Decorate file link
      // Precondition:
      //    about   -- class distinction string;  false if invalid target
      //    apply   -- style string; or false if invalid target
      //    assign  -- page title, if valid target
      // Postcondition:
      //    Current link is decorated
      // Uses:
      //    >  .guide.cats.invalid
      //    >  .guide.stateMin
      //    >  .guide.stateMax
      //    >< .str.artPath
      //    .str.trimRight()
      // 2012-02-22 PerfektesChaos@de.wikipedia
      var elem    =  false;
      var i;
      var ref;
      var set;
      var seek;
      var select;
      var style   =  FAdm.guide.cats.invalid;
      var swap;
      if ( apply ) {
         seek  =  FAdm.str.artPath + assign;
         for ( i = FAdm.guide.stateMin;
               i < FAdm.guide.stateMax;
               i++ ) {
            ref   =  document.links[i];
            swap  =  decodeURI( ref.pathname ).replace( /_/g, " " );
            if ( unescape( swap )  ===  seek ) {
               elem  =  ref;
               i++;
               if ( i < document.links.length ) {
                  ref   =  document.links[i];
                  swap  =  decodeURI( ref.pathname );
                  swap  =  swap.replace( /_/g, " " );
                  if ( unescape( swap )  ===  seek ) {
                     elem  =  ref;
                  }
               }
               style  =  apply;
               break;   // for i
            }
         }   // for i
      } else {
         elem  =  document.links[ FAdm.guide.stateMin ];
      }
      if ( elem ) {
         elem.setAttribute( "style", style );
         if ( about ) {
            select  =  "fileAdm_F_" + about;
            set     =  "class";
            if ( elem.hasAttribute( set ) ) {
               select  =  FAdm.str.trimRight( elem.getAttribute( set ) )
                          + " " + select;
            }
            elem.setAttribute( set, select );
         }
      }
   };   // .guide.flag()



   FAdm.guide.flipImage  =  function ( abolish ) {
      // Toggle thumbnail images display, if any
      // Precondition:
      //    abolish  -- true: suppress thumbnail images
      //    Toggle link was created
      // Postcondition:
      //    Image appearance toggled
      //    Toggle link is changed
      // Uses:
      //    >  .ns.is
      //    >  .str.page.scp
      //    >  .guide.toggleImg
      //    >     .id
      //    >  .opt.lessMini
      //     < .guide.$mins
      //    .portlet.flip()
      //    .opt.fetch()
      // Remark: Used as event handler -- 'this' is not FAdm.guide
      // 2011-12-31 PerfektesChaos@de.wikipedia
      var selector  =  ".thumb";
      var style;
      if ( FAdm.ns.is === -1 ) {
         if ( FAdm.str.page.scp ===  "Listfiles" ) {
//          selector  =  ".TablePager_col_thumb";
            selector  =  "a.image";
         }
      }
      FAdm.guide.$mins  =  jQuery( selector );
      if ( FAdm.guide.$mins.length ) {
         if ( FAdm.guide.styleImg ) {
            style  =  FAdm.guide.styleImg;
         } else {
            style  =  FAdm.guide.$mins.first().attr( "style" );
            if ( typeof( style )  ===  "string" ) {
               FAdm.guide.styleImg  =  style;
            } else {
               FAdm.guide.styleImg  =  true;
            }
         }
         if ( abolish ) {
            style  =  "display:none";
         }
         if ( typeof( style )  ===  "string" ) {
            FAdm.guide.$mins.attr( "style", style );
         } else {
            FAdm.guide.$mins.removeAttr( "style" );
         }
         FAdm.portlet.flip( FAdm.guide.toggleImg, abolish );
         FAdm.opt.fetch( FAdm.opt.lessMini, abolish );
      } else if ( FAdm.guide.toggleImg.id ) {
         jQuery( "#" + FAdm.guide.toggleImg.id ).css( "display",
                                                      "none" );
      }
   };   // .guide.flipImage()



   FAdm.guide.flipTarget  =  function ( appear ) {
      // Toggle separate target window/tab for single file description
      // Precondition:
      //    appear  -- true: show single page in separate window
      //    Toggle link was created
      // Postcondition:
      //    Target page behaviour toggled
      //    Link targets changed
      // Uses:
      //    >  .guide.toggleTgt
      //    >  .opt.multiWin
      //     < .wins.lot
      //    .portlet.flip()
      //    .opt.fetch()
      //    .wins.forwardSingle()
      //    .cat.flip()
      // Remark: Used as event handler -- 'this' is not FAdm.guide
      // 2011-08-31 PerfektesChaos@de.wikipedia
      FAdm.wins.lot  =  appear;
      FAdm.portlet.flip( FAdm.guide.toggleTgt, FAdm.wins.lot );
      FAdm.opt.fetch( FAdm.opt.multiWin, FAdm.wins.lot );
      FAdm.wins.forwardSingle();
      FAdm.cat.flip();
   };   // .guide.flipTarget()



   FAdm.guide.found  =  function ( arrived ) {
      // Postprocess file entry on guiding page list after ajax request
      // Precondition:
      //    arrived  -- JSON result of ajax query for guiding page
      // Postcondition:
      //    DOM element A got appropriate colours
      // Uses:
      //    >  .guide.cats
      //    .guide.furnish()
      //    .guide.flag()
      //    .guide.fancy()
      // Remark: Used as event handler -- 'this' is not FAdm.guide
      // 2011-11-30 PerfektesChaos@de.wikipedia
      var i;
      var n;
      var page;
      var query  =  ( typeof( arrived )  ===  "object" );
      var sel;
      var sid;
      var style;
      var type;
      FAdm.guide.furnish();
      if ( query ) {
         query  =  arrived.query;
      }
      if ( query ) {
         n  =  query.pageids.length;
         if ( n ) {
            for ( i = 0;  i < n;  i++ ) {
               sid  =  query.pageids[i];
               if ( sid.charCodeAt( 0 )  ===  45 ) {   // '-'
                  FAdm.guide.flag( false, false );
               } else {
                  sel    =  false;
                  style  =  false;
                  page   =  query.pages[sid];
                  if ( typeof( page.categories )  ===  "object" ) {
                     type   =  FAdm.guide.fancy( page.categories, true );
                     sel    =  type[0];
                     style  =  type[1];
                  }
                  FAdm.guide.flag( sel, style, page.title );
               }
            }   // for i
         } else {
            FAdm.guide.flag( false, false );
         }
      } else {
         FAdm.guide.flag( false, false );
      }
      FAdm.guide.fetch();
   };   // .guide.found()



   FAdm.guide.fulfil  =  function ( about, aim ) {
      // Test whether a title matches an operational condition
      // Precondition:
      //    about  -- string to be tested
      //    aim    -- operational guide.cats array[3]
      // Postcondition:
      //    Returns style if matching, or false
      // 2011-08-03 PerfektesChaos@de.wikipedia
      var r  =  false;
      switch ( aim[1] ) {
         case 0 :   // equals string
            r  =  ( about === aim[0] );
            break;
         case 1 :   // start with string
            r  =  ( about.indexOf( aim[0] )  ===  0 );
            break;
         case 2 :   // test RegExp
            r  =  aim[0].test( about );
            break;
      }   // switch aim[1]
      if ( r ) {
         r  =  aim[2];
      }   //
      return r;
   };   // .guide.fulfil()



   FAdm.guide.furnish  =  function () {
      // Change human readable category style definition into operational
      // Postcondition:
      //    .guide.cats are accelerated
      // Uses:
      //    >  .guide.cats
      //    >  .ns.nCat
      //    >  .cat.start
      //    >< .ns.sCat
      //    >< .guide.cats.lazyRE
      //    >< .guide.cats.checking
      //    >< .guide.cats.review0
      //    >< .guide.cats.review1
      //    >< .guide.cats.review2
      //    >< .guide.cats.license
      //    >< .guide.cats.transfer
      //    >< .guide.cats.transit
      //    >< .guide.cats.transfix
      //    >< .guide.cats.trash
      //    .guide.furnisher()
      // 2011-09-19 PerfektesChaos@de.wikipedia
      var gcs  =  this.cats;
      if ( gcs.lazyRE ) {
         gcs.lazyRE  =  false;
         if ( ! FAdm.ns.sCat ) {
            FAdm.ns.sCat  =  FAdm.ns.fetch( FAdm.ns.nCat );
         }
         gcs.category  =  [ FAdm.cat.start, 1, gcs.category ];
         gcs.checking  =  this.furnisher( gcs.checking );
         gcs.license   =  this.furnisher( gcs.license );
         gcs.review0   =  this.furnisher( gcs.review0 );
         gcs.review1   =  this.furnisher( gcs.review1 );
         gcs.review2   =  this.furnisher( gcs.review2 );
         gcs.transfer  =  this.furnisher( gcs.transfer );
         gcs.transit   =  this.furnisher( gcs.transit );
         gcs.transmit  =  this.furnisher( gcs.transmit );
         gcs.transfix  =  this.furnisher( gcs.transfix );
         gcs.trash     =  this.furnisher( gcs.trash );
      }
   };   // .guide.furnish()



   FAdm.guide.furnisher  =  function ( adjust ) {
      // Prepare mapping of category
      // Precondition:
      //    adjust  --  human readable guide.cats element (Array[2])
      //                adjust[0]  -- match: title string, or Array
      //                adjust[1]  -- style
      // Postcondition:
      //    Returns operational guide.cats element
      //            Array[3]  [0]  -- match: name string, or RegExp
      //                      [1]  -- mode
      //                              0: equals string
      //                              1: start with string
      //                              2: test RegExp
      //                      [2]  -- style = adjust[1]
      // Uses:
      //    >  .ns.sCat
      //    .str.substrEnd()
      // 2011-08-24 PerfektesChaos@de.wikipedia
      var i;
      var r   =  [ adjust[0], 0, adjust[1] ];
      var re;
      switch ( typeof( adjust[0] ) ) {
         case "string" :
            if ( FAdm.str.substrEnd( r[0], 2 )  ===  ".*" ) {
               r[0]  =  r[0].substr( 0,  r[0].length - 2 );
               r[1]  =  1;
            }
            r[0]  =  FAdm.ns.sCat + ":" + r[0];
            break;
         case "object" :   // Array
            re  =  "^" + FAdm.ns.sCat + ":(";   //// ns, escapeRegexp
            for ( i = 0;  i < r[0].length;  i++ ) {
               if ( i ) {
                  re  =  re + "|";
               }
               re  =  re + r[0][i];
            }   // for i
            re    =  re + ")$";
            r[0]  =  new RegExp( re );
            r[1]  =  2;
            break;
      }   // switch typeof(adjust[0])
      return r;
   };   // .guide.furnisher()



   FAdm.guide.further  =  function ( advanced, assign ) {
      // Equip guiding page with review state link
      // Precondition:
      //    advanced  -- true: advanced functionality (Review User)
      //    assign    -- true: set cookie
      //    Page is supposed to be a view on a guiding page
      // Postcondition:
      //    Cookie is set
      // Uses:
      //    .users.flag()
      // 2011-08-18 PerfektesChaos@de.wikipedia
      if ( assign ) {
         FAdm.users.flag( "R", advanced );
      }
   };   // .guide.further()



   FAdm.guide.xClm.fill  =  function ( ahead ) {
      // Add column to Special:Listfiles table, or update
      // Precondition:
      //    ahead  -- true: setup column
      //    Current page is Special:Listfiles
      // Uses:
      //    >  .guide.xClm.portlet
      // 2011-09-19 PerfektesChaos@de.wikipedia
      var s;
      var sort;
      var xClm  =  this;
      var $r;
      var $tbl;
      var $th;
      if ( ahead ) {
         $tbl  =  jQuery( ".TablePager" );
         if ( $tbl.length ) {
            sort  =  $tbl.attr( "class" );
            this.portlet.setAttribute( "style", "display:none" );
            $tbl.attr( "class",  sort + " sortable" );
            $r  =  jQuery( ".TablePager > thead > tr" );
            if ( $r.length ) {
               $r.children().each( function() {
                                             $th   =  $( this );
                                             sort  =  $th.attr( "class" )
                                                      + " unsortable";
                                             $th.attr( "class", sort );
                                               } );
               $th  =  jQuery( "<th />" );
               if ( $th.length ) {
                  $th.text( "*" );
                  $th.attr( "class", "sortable" );
                  $r.children().last().after( $th );
               }
            }
         }
      }
      $r  =  jQuery( ".TablePager > tbody > tr" );
      if ( $r.length ) {
         if ( ahead ) {
            s  =  "<td class='TablePager_col_fileAdm'>";
            $r.each( function() { $( this ).children().last().after( s );
                                 } );
         }
         $r.each( function() { xClm.td  =  { $cell: false,
                                             $kids: $( this ).children(),
                                             scope: false };
                               xClm.td.$kids.each( xClm.find );
                               xClm.furnish();
                              } );
      }
      if ( this.td ) {
         delete this.td;
      }
   };   // .guide.xClm.fill()



   FAdm.guide.xClm.find  =  function ( index, Element ) {
      // Examine any Special:Listfiles table cell in row
      // Precondition:
      //    index    -- number of table cell in row
      //    Element  -- table cell
      // Uses:
      //     < .guide.xClm.td.scope
      //     < .guide.xClm.td.$cell
      // Remark: Used as event handler -- 'this' is not FAdm.guide.xClm
      // 2011-09-19 PerfektesChaos@de.wikipedia
      var s;
      var xClm   =  FAdm.guide.xClm;
      var $elem  =  jQuery( this );
      switch ( $elem.attr( "class" ) ) {
         case "TablePager_col_img_name" :
            $elem  =  $elem.find( "a" );
            if ( $elem.length ) {
               s  =  $elem.attr( "class" );
               if ( typeof( s )  ===  "string" ) {
                  if ( s.indexOf( "fileAdm_F_" )  ===  0 ) {
                     xClm.td.scope  =  s.substr( 10 );
                  }
               }
            }
            break;
         case "TablePager_col_fileAdm" :
            xClm.td.$cell  =  $elem;
            break;
      }   // switch class
   };   // .guide.xClm.furnish()



   FAdm.guide.xClm.furnish  =  function () {
      // Update content of Special:Listfiles additional cell
      // Precondition:
      //    Current page is Special:Listfiles; .guide.xClm.td is filled
      // Uses:
      //    >  .guide.xClm.td.$cell
      //    >  .guide.xClm.td.scope
      // 2011-09-19 PerfektesChaos@de.wikipedia
      var s;
      if ( this.td.$cell ) {
         s  =  ( this.td.scope ? this.td.scope : "" );
         this.td.$cell.text( s );
      }
   };   // .guide.xClm.furnish()



};   // .bb.guide()
mediaWiki.libs.fileAdm.bb.guide( mediaWiki.libs.fileAdm, mediaWiki, jQuery);
delete mediaWiki.libs.fileAdm.bb.guide;



//-----------------------------------------------------------------------



mediaWiki.libs.fileAdm.bb.lang  =  function ( FAdm ) {
   // Language related
   // 2012-06-07 PerfektesChaos@de.wikipedia
   "use strict";
   if ( typeof FAdm.lang !== "object" ) {
      FAdm.lang  =  { };
   }
   FAdm.lang.sc3  =  "ace|als|ang|arc|ast|ast|" +
                     "bar|bcl|bjn|bpy|bug|bxr|" +
                     "cdo|ceb|cho|chr|chy|ckb|crh|csb|" +
                     "diq|dsb|" +
                     "eml|epo|ext|" +
                     "frp|frr|fur|" +
                     "gag|gan|glk|got|gsw|" +
                     "hak|haw|hif|hsb|" +
                     "ilo|" +
                     "jbo|" +
                     "kaa|kab|kbd|koi|krc|ksh|" +
                     "lad|lbe|lez|lij|lmo|ltg|lzh|" +
                     "mdf|mhr|mrj|mus|mwl|myv|mzn|" +
                     "nah|nan|nap|nds|new|nov|nrm|nso|" +
                     "pag|pam|pap|pcd|pdc|pfl|pih|pms|pnb|pnt|" +
                     "rmy|rue|" +
                     "scn|scn|sco|sgs|srn|stq|szl|" +
                     "tet|tpi|tum|" +
                     "udm|" +
                     "vec|vep|vls|vro|" +
                     "war|wuu|" +
                     "wuu|" +
                     "xal|xmf|" +
                     "yue|" +
                     "zea";   // 2012-06-20
   FAdm.lang.sre  =  "[a-z][a-z][a-z]?"
                     + "|simple"
                     + "|[a-z][a-z][a-z]?-[a-z][a-z][-a-z]*";



   FAdm.lang.flop  =  function ( adjust ) {
      // Analyze whether prefix is not a wikiproject language code
      // Precondition:
      //    adjust    -- heading characters before ':' in a wikilink
      // Postcondition:
      //    Returns false   iff language in any wikiproject
      //            String  iff heading part of page name
      //    RegExp was used.
      // Uses:
      //    >  .lang.sre
      //    >  .lang.sc3
      //    >< .lang.re
      //    .str.trimLeft()
      //    .lang.isO_639_1()
      // 2013-01-11 PerfektesChaos@de.wikipedia
      var got;
      var k;
      var r;
      var s    =  FAdm.str.trimLeft( adjust );
      if ( ! this.re ) {
         this.re  =  new RegExp( "^(" + this.sre + ") *$",  "i" );
      }
      got  =  this.re.exec( s );
      if ( got ) {
         r    =  s;
         got  =  got[1];
         s    =  got.toLowerCase();
         k    =  got.length;
         if ( k === 2 ) {
            if ( s === "wp" ) {
               r  =  "WP";
            } else if ( this.isO_639_1( s ) ) {
               r  =  false;
            }
         } else if ( k === 3 ) {
            if ( s === "doi" ) {
               r  =  s;
            } else if ( this.sc3.indexOf( s )  >=  0 ) {
               r  =  false;
            }
         } else if ( s === "simple" ) {
   //    } else if ( slang === "tokipona" ) {
         } else if ( k > 5 ) {
            k  =  s.indexOf( "-" );
            if ( k === 2  ||  k === 3 ) {
               /*  |bat-smg|be-x-old|cbk-zam|fiu-vro|map-bms|nds-nl
                   |roa-rup|roa-tara|ru-sib
                   |zh-classical|zh-min-nan|zh-yue|  */
               if (/^[a-z][a-z][a-z]?-[a-z][a-z][\-a-z]*/.test(got)) {
                  r  =  false;
               }
            }
         }
      } else {
         r  =  s;
      }   // matching lang?
      return r;
   };   // .lang.flop()



   FAdm.lang.isO_639_1  =  function ( ask ) {
      // Is string a valid ISO 639-1 language code?
      // Precondition:
      //    ask  -- lowercase 2 letter query string
      // Postcondition:
      //    Returns  true  iff  ask is a valid ISO 639-1 language code
      // 2010-07-18 PerfektesChaos@de.wikipedia
      var s  =   "|aa|ab|ae|af|ak|am|an|ar|as|av|ay|az"
            + "|ba|be|bg|bh|bi|bm|bn|bo|br|bs"
            + "|ca|ce|ch|co|cr|cs|cu|cv|cy"
            + "|da|de|dv|dz"
            + "|ee|el|en|eo|es|et|eu"
            + "|fa|ff|fi|fj|fo|fr|fy"
            + "|ga|gd|gl|gn|gu|gv"
            + "|ha|he|hi|ho|hr|ht|hu|hy|hz"
            + "|ia|id|ie|ig|ii|ik|io|is|it|iu"
            + "|ja|jv"
            + "|ka|kg|ki|kj|kk|kl|km|kn|ko|kr|ks|ku|kv|kw|ky"
            + "|la|lb|lg|li|ln|lo|lt|lu|lv"
            + "|mg|mh|mi|mk|ml|mn|mr|ms|mt|my"
            + "|na|nb|nd|ne|ng|nl|nn|no|nr|nv|ny"
            + "|oc|oj|om|or|os"
            + "|pa|pi|pl|ps|pt"
            + "|qu"
            + "|rm|rn|ro|ru|rw"
            + "|sa|sc|sd|se|sg|sh|si|sk|sl|sm|sn|so|sq|sr|ss|st|su|sv|sw"
            + "|ta|te|tg|th|ti|tk|tl|tn|to|tr|ts|tt|tw|ty"
            + "|ug|uk|ur|uz"
            + "|ve|vi|vo"
            + "|wa|wo"
            + "|xh"
            + "|yi|yo"
            + "|za|zh|zu|";
      return  ( s.indexOf( ask )  >  0 );
   };   // .lang.isO_639_1()



};   // .bb.lang()
mediaWiki.libs.fileAdm.bb.lang( mediaWiki.libs.fileAdm );
delete mediaWiki.libs.fileAdm.bb.lang;



//-----------------------------------------------------------------------



mediaWiki.libs.fileAdm.bb.misc  =  function ( FAdm, mw ) {
   // Misc utilities
   // 2012-09-15 PerfektesChaos@de.wikipedia
   "use strict";
   if ( typeof FAdm.misc !== "object" ) {
      FAdm.misc  =  { lean:    false };
   }



   FAdm.misc.message  =  function ( apply, assign, always, absolute ) {
      // Show message similar to mw.util.jsMessage() MW 1.19
      // Precondition:
      //    apply     -- HTML box content
      //    assign    -- identifier (unused since mw.util.jsMessage())
      //    always    -- true: keep visible; else enable diminishing
      //    absolute  -- CSS property assignments like width
      // Uses:
      //    >< .misc.lean
      //    >< .misc.$msg
      //    >< .misc.$msgTop
      //    mw.util.addCSS()
      //    jQuery()
      // 2012-09-15 PerfektesChaos@de.wikipedia
      var $e;
      var s;
      if ( ! this.lean ) {
         mw.util.addCSS(".cn-fundraiser-banner,"
                        + "#mw-js-message,"
                        + "#siteNotice,"
                        + "#fundraising\n"
                        + "{display: none;}");
         this.lean  =  true;
      }
      if ( apply ) {
         if ( absolute ) {
            if ( this.$msgTop ) {
               this.$msgTop.empty();
            } else {
               $e  =  jQuery( "#content" );
               if ( $e.length ) {
                  s             =  "<div class='fileAdmTop'></div>";
                  this.$msgTop  =  jQuery( s );
                  $e.before( this.$msgTop );
               }
            }
            if ( this.$msgTop ) {
               s  =  "position:  relative;" +
                     "display:   block;" +
                     absolute;
                           // position: absolute;
                           // right:    1em;
                           // top:      7em;
                           // width:    20em;
               this.$msgTop.attr( "style", s );
               this.$msgTop.append( apply );
            }
         } else {
            if ( this.$msg ) {
               this.$msg.empty();
            } else {
               $e  =  jQuery( "#bodyContent" );
               if ( ! $e.length ) {
                  $e  =  jQuery( "#article" );
                  if ( ! $e.length ) {
                     $e  =  jQuery( "#content" );
                  }
               }
               if ( $e.length ) {
                  this.$msg  =  jQuery( "<div class='fileAdm'></div>" );
                  $e.before( this.$msg );
               }
            }
            if ( this.$msg ) {
               s  =    "display:   block;"
                     + "font-size: 90%;";
               this.$msg.attr( "style", s );
               this.$msg.append( apply );
            }
         }
      } else {
         if ( this.$msgTop ) {
            this.$msgTop.attr( "style", "display: none;" );
         }
         if ( this.$msg ) {
            this.$msg.attr( "style", "display: none;" );
         }
      }
   };   // .misc.message()



};   // .bb.misc()
mediaWiki.libs.fileAdm.bb.misc( mediaWiki.libs.fileAdm, mediaWiki );
delete mediaWiki.libs.fileAdm.bb.misc;



//-----------------------------------------------------------------------



mediaWiki.libs.fileAdm.bb.ns  =  function ( FAdm, mw ) {
   // Namespace related
   // 2012-08-30 PerfektesChaos@de.wikipedia
   "use strict";
   if ( typeof FAdm.ns !== "object" ) {
      FAdm.ns  =  { };
   }



   FAdm.ns.fetch  =  function ( access ) {
      // Fetch namespace related information
      // Precondition:
      //    access  -- namespace number
      // Postcondition:
      //    Returns formatted namespace name
      // Uses:
      //    >< .ns.map
      //    .str.fromNum()
      //    mw.config.get()
      // 2011-10-09 PerfektesChaos@de.wikipedia
      var r;
      if ( ! FAdm.ns.map ) {
         FAdm.ns.map  =  mw.config.get( "wgFormattedNamespaces" );
      }
      r  =  FAdm.ns.map[ FAdm.str.fromNum( access ) ];
      return r;
   };   // .ns.fetch()



};   // .bb.ns()
mediaWiki.libs.fileAdm.bb.ns( mediaWiki.libs.fileAdm, mediaWiki );
delete mediaWiki.libs.fileAdm.bb.ns;



//-----------------------------------------------------------------------



mediaWiki.libs.fileAdm.bb.opt  =  function ( FAdm, mw ) {
   // User option administration
   // 2012-09-15 PerfektesChaos@de.wikipedia
   "use strict";
   if ( typeof FAdm.opt !== "object" ) {
      FAdm.opt  =  { control: { },
                     page:    { }  };
   }
   if ( typeof FAdm.opt.control !== "object" ) {
      FAdm.opt.control  =  { };
   }
   if ( typeof FAdm.opt.page !== "object" ) {
      FAdm.opt.page  =  { };
   }



   FAdm.opt.factory  =  function ( arglist ) {
      // Create toggle link from general definition
      // Precondition:
      //    arglist  -- object with definition
      //                >  .hint     -- tooltip
      //                >  .hotkey   -- single character
      //                >  .name     -- toggle distinguisher
      //                >  .title    -- constant link title
      // Postcondition:
      //    Returns true if toggle was created
      //    arglist modified
      //             < .click    -- function
      //             < .id       -- control id distinguisher
      //             < .varText  -- SPAN for variable link text
      // Uses:
      //    .portlet.factory()
      // 2011-08-31 PerfektesChaos@de.wikipedia
      var r  =  false;
      arglist.click  =  "void(0);";
      arglist.id     =  "ca-toggle-" + arglist.name;
      FAdm.portlet.factory( arglist );
      if ( arglist.a ) {
         arglist.varText  =  document.createElement( "span" );
         if ( arglist.varText ) {
            r  =  true;
            arglist.a.dom.appendChild( arglist.varText );
            arglist.varText.textContent  =  "* * *";
         }
      }
      return r;
   };   // .opt.factory()



   FAdm.opt.fetch  =  function ( arglist, already ) {
      // Retrieve option data from cookie or user script if no cookie
      // Precondition:
      //    arglist  -- object with definition
      //                >  .env  -- user script environment identifier
      //                >  .obj  -- object value if user defined
      //                >  .val  -- fallback value if not yet suggested
      //                >  .typ  -- typeof required value
      //    already  -- current value if known
      // Postcondition:
      //    Returns option data
      // Uses:
      //    >  .opt.keep
      //    .str.fromNum()
      //    jQuery.cookie()
      // 2013-01-12 PerfektesChaos@de.wikipedia
      var expiry  =  { expires: null,
                       path:    "/" };
      var r;
      var re0     =  /^(false|0)$/;
      var re1     =  /^(true|1)$/;
      var spec    =  "fileAdm_" + arglist.env;
      var store;
      if ( already === undefined ) {
         store  =  jQuery.cookie( spec );
         if ( typeof( store )  ===  "string" ) {
            if ( arglist.typ === "number" ) {
               if ( store !== "NaN" ) {
                  r  =  store;
               }
            } else {
               r  =  store;
            }
         }
      } else {
         r  =  already;
      }
      if ( r === undefined  &&  arglist.obj !== undefined ) {
         r  =  arglist.obj;
      }
      if ( r === undefined ) {
         r  =  arglist.val;
      }
      switch ( typeof( r ) ) {
         case "string" :
            switch ( arglist.typ ) {
               case "boolean" :
                  if ( re0.test( store ) ) {
                     r  =  false;
                  } else if ( re1.test( store ) ) {
                     r  =  true;
                  }
                  break;
               case "choice" :
                  r  =  r.toLowerCase();
                  break;
               case "number" :
                  r  =  parseInt( r, 10 );
                  break;
            }   // switch arglist.typ
            store  =  r;
            break;
         case "boolean" :
            store  =  ( r ? "true" : "false" );
            break;
         case "number" :
            store  =  FAdm.str.fromNum( r );
            break;
      }   // switch typeof(r)
      if ( this.keep < 0 ) {
         store  =  null;
      } else if ( this.keep > 0 ) {
         expiry.expires  =  this.keep;
      }
      jQuery.cookie( spec, store, expiry );
      return r;
   };   // .opt.fetch()



   FAdm.opt.fire  =  function () {
      // Reaction on user submission of options form
      // Precondition:
      //    Submit action of options form
      // Uses:
      //    >  .opt.memory
      //    >  .opt.multiWin
      //    >  .opt.lessMini
      //    >  .opt.watchQ
      //    >  .opt.watchT
      //     < .opt.keep
      //     < .batch.watchQ
      //     < .batch.watchT
      //     < .wins.lot
      //     < .guide.lessMini
      //    .opt.fired()
      //    .opt.fetch()
      //    .opt.fresh()
      // 2013-01-27 PerfektesChaos@de.wikipedia
      if ( this.fired( "fA-radio_memory_0" ) ) {
         this.keep  =  0;
      } else if ( this.fired( "fA-radio_memory_28" ) ) {
         this.keep  =  28;
      } else {
         this.keep  =  -1;
      }
      if ( this.fired( "fA-radio_watchQ_preferences" ) ) {
         FAdm.batch.watchQ  =  "preferences";
      } else if ( this.fired( "fA-radio_watchQ_nochange" ) ) {
         FAdm.batch.watchQ  =  "nochange";
      } else if ( this.fired( "fA-radio_watchQ_unwatch" ) ) {
         FAdm.batch.watchQ  =  "unwatch";
      } else {
         FAdm.batch.watchQ  =  "watch";
      }
      if ( this.fired( "fA-radio_watchT_preferences" ) ) {
         FAdm.batch.watchT  =  "preferences";
      } else if ( this.fired( "fA-radio_watchT_nochange" ) ) {
         FAdm.batch.watchT  =  "nochange";
      } else if ( this.fired( "fA-radio_watchT_unwatch" ) ) {
         FAdm.batch.watchT  =  "unwatch";
      } else {
         FAdm.batch.watchT  =  "watch";
      }
      this.fetch( this.memory, this.keep );
      FAdm.guide.lessMini  =  this.fired( "fA-radio_lessMini_true" );
      FAdm.wins.lot        =  this.fired( "fA-radio_multiWin_true" );
      this.fetch( this.multiWin, FAdm.wins.lot );
      this.fetch( this.lessMini, FAdm.guide.lessMini );
      this.fetch( this.watchQ, FAdm.batch.watchQ );
      this.fetch( this.watchT, FAdm.batch.watchT );
      this.fresh();
   };   // .opt.fire()



   FAdm.opt.fired  =  function ( access ) {
      // Retrieve checked value of radio button or checkbox
      // Precondition:
      //    access  -- element selector (without leading "#")
      // Postcondition:
      // Uses:
      //    Returns true or false, else undefined
      // 2011-10-12 PerfektesChaos@de.wikipedia
      //    jQuery( "input:radio[name=bar]:checked" ).val();
      var r;
      var $el  =  jQuery( "#" + access );
      if ( $el.length ) {
         if ( $el.prop( "checked" ) ) {
            r  =  true;
         } else {
            r  =  false;
         }
      }
      return r;
   };   // .opt.fired()



   FAdm.opt.fit  =  function () {
      // Initialize user options from object
      // Uses:
      //    >  .options.*
      //    >  .opt.memory
      //    >  .opt.lessMini
      //    >  .opt.multiWin
      //    >  .opt.watchQ
      //    >  .opt.watchT
      //    .opt.fitter()
      // 2013-01-12 PerfektesChaos@de.wikipedia
      if ( typeof( FAdm.options )  ===  "object" ) {
         this.fitter( this.memory );
         this.fitter( this.lessMini );
         this.fitter( this.multiWin );
         this.fitter( this.watchQ );
         this.fitter( this.watchT );
      }
   };   // .opt.fit()



   FAdm.opt.fitter  =  function ( arglist ) {
      // Initialize user option from object
      // Precondition:
      //    arglist  -- object with definition
      //                >  .env  -- identifier in .opt.user
      //                >  .typ  -- required type
      //                 < .obj  -- value taken
      //    .options is an object
      // Uses:
      //    >  .options.*
      //     < .opt.*.val
      // 2013-01-12 PerfektesChaos@de.wikipedia
      var s,
          v  =  FAdm.options[ arglist.env ];
      if ( v !== undefined ) {
         s  =  ( arglist.typ === "choice"  ?  "string"  :  arglist.typ );
         if ( typeof( v ) === s ) {
            arglist.obj  =  v;
         }
      }
   };   // .opt.fitter()



   FAdm.opt.fresh  =  function () {
      // Transfer option data set into application
      // Uses:
      //    >  .opt.multiWin
      //    >  .opt.lessMini
      //    >  .opt.watchQ
      //    >  .opt.watchT
      //     < .wins.lot
      //     < .guide.lessMini
      //     < .batch.watchQ
      //     < .batch.watchT
      // 2013-01-13 PerfektesChaos@de.wikipedia
      FAdm.wins.lot        =  FAdm.opt.fetch( FAdm.opt.multiWin );
      FAdm.guide.lessMini  =  FAdm.opt.fetch( FAdm.opt.lessMini );
      FAdm.batch.watchQ    =  FAdm.opt.fetch( FAdm.opt.watchQ );
      FAdm.batch.watchT    =  FAdm.opt.fetch( FAdm.opt.watchT );
   };   // .opt.fresh()



   FAdm.opt.control.factory  =  function ( access, aim, apply, assign, active ) {
      // Create <input> string
      // Precondition:
      //    access  -- element selector (without leading "#")
      //    aim     -- 'submit' or 'radio', 'checkbox', 'text'
      //    apply   -- initial string, or true if checked; 'submit' label
      //    assign  -- group or event name
      //    active  -- boolean: enabled or disabled control
      // Postcondition:
      //    Returns input element string
      // Remark:
      //    IE requires type='...' already on jQuery creation
      // 2011-09-28 PerfektesChaos@de.wikipedia
      var r    =  "<input id='" + access + "' type='" + aim + "'";
      var show;
      switch ( aim ) {
         case "radio" :
            r  =  r + " name='" + assign + "'";
            // fall through
         case "checkbox" :   //
            if ( apply ) {
               r  =  r + " checked='init'";
            }
            break;
         case "text" :
            if ( apply ) {
               if ( apply.length ) {
                  show  =  apply.replace( /\x27/g, "%27" );   // '
                  r     =  r + " value='" + show + "'";
               }
            }
            break;
         case "submit" :
            r  =  r + " value='"
                    +  ( apply.length ? apply : "Submit" )
                    +  "'";
            break;
      }   // switch
      if ( typeof( active ) === "boolean" ) {
         if ( ! active ) {
            r  =  r + " disabled'";
         }
      }
      r  =  r + ">";
      return r;
   };   // .opt.control.factory()



   FAdm.opt.control.formel  =  function ( arglist ) {
      // Create <input> string for checkbox
      // Precondition:
      //    arglist  -- object with definition
      //                >  .active   -- not disabled
      //                >  .checked  -- initial value
      //                >  .id       -- identifier
      //                >  .hint     -- tooltip
      // Postcondition:
      //    Returns jQuery element
      // Uses:
      //    .opt.control.factory()
      // 2011-09-28 PerfektesChaos@de.wikipedia
      var s   =  this.factory( arglist.id,
                               "checkbox",
                               arglist.checked,
                               undefined,
                               arglist.active );
      var $r  =  jQuery( s );
      if ( arglist.hint ) {
         $r.attr( "title", arglist.hint );
      }
      return $r;
   };   // .opt.control.formel()



   FAdm.opt.page.form  =  function () {
      // Decorate user options form page
      // Precondition:
      //    Current page is user options form page
      // Postcondition:
      //    Page is decorated and converted into form
      // Uses:
      //    >  .str.call
      //    >  .opt.memory
      //    >  .wins.lot
      //    >  .guide.lessMini
      //    >  .batch.watchQ
      //    >  .batch.watchT
      //    >  .users.n
      //    >  mw.util.$content
      //    >< .opt.keep
      //     < .opt.page.$table
      //    .opt.fetch()
      //    .opt.fresh()
      //    .users.fetch()
      //    .opt.page.forming()
      //    .opt.page.formula()
      //    .opt.page.format()
      //    .opt.page.found()
      //    jQuery.find()
      //    (.opt.fire)
      // 2013-01-13 PerfektesChaos@de.wikipedia
      var script;
      var watches;
      var $form   =  jQuery( "#fA-form1" );
      jQuery( "#fA_noscript" ).remove();
      if ( $form.length ) {
         script   =  FAdm.str.call + "opt.fire();void(0);";
         watches  =  [ "preferences", "watch",
                       "nochange", "unwatch" ];
         $form.wrap( "<form action='" + script + "' method='POST'>" );
         FAdm.opt.keep  =  FAdm.opt.fetch( FAdm.opt.memory );
         FAdm.opt.fresh();
         FAdm.users.fetch();
         this.forming( "memory",  FAdm.opt.keep,  [-1, 0, 28] );
         this.forming( "multiWin", FAdm.wins.lot );
         this.forming( "lessMini", FAdm.guide.lessMini );
         this.forming( "watchQ", FAdm.batch.watchQ, watches );
         this.forming( "watchT", FAdm.batch.watchT, watches );
         this.formula( "TUSC1cn", FAdm.users.n, 40, 100 );
         this.formula( "TUSC1pw", false, 40, 40 );
         this.format( "fA-form1-submit", "submit" );
         // click ---> ???? .opt.fire()
         this.$table  =  mw.util.$content.find( "#fA-form1" );
         this.found( "memory" );
         this.found( "multiWin" );
         this.found( "lessMini" );
         this.found( "watchQ" );
         this.found( "watchT" );
      }
   };   // .opt.page.form()



   FAdm.opt.page.format  =  function ( access, aim, apply, assign ) {
      // Convert <div> into <input>
      // Precondition:
      //    access  -- element selector (without leading "#")
      //    aim     -- "submit" or "radio" or "checkbox"  or "text"
      //    apply   -- initial string, or true if checked
      //    assign  -- group or event name
      // Postcondition:
      //    Returns input element
      // Uses:
      //    .opt.control.factory()
      // 2011-09-08 PerfektesChaos@de.wikipedia
      var r     =  false;
      var show;
      var $el  =  jQuery( "#" + access );
      if ( $el.length ) {
         show  =  apply;
         if ( aim === "submit" ) {
            show  =  $el.text();
         }
         r  =  $el.replaceWith( FAdm.opt.control.factory( access,
                                                          aim,
                                                          show,
                                                          assign ) );
      }
      return r;
   };   // .opt.page.format()



   FAdm.opt.page.forming  =  function ( access, apply, allow ) {
      // Convert <div> into <input type='radio'>
      // Precondition:
      //    access  -- element group selector
      //    apply   -- initial check state
      //    allow   -- optional array, if not boolean
      // Postcondition:
      //    Radio element created and initialized
      // Uses:
      //    .opt.page.format()
      // 2011-09-08 PerfektesChaos@de.wikipedia
      var i;
      var k;
      var n;
      var start  =  "fA-radio_" + access;
      var $el;
      var $false;
      var $true;
      if ( typeof( apply ) === "boolean" ) {
         $false  =  this.format( start + "_false",
                                 "radio",
                                 ! apply,
                                 start );
         $true   =  this.format( start + "_true",
                                 "radio",
                                 apply,
                                 start );
      } else if ( typeof( allow )  ===  "object" ) {
         n  =  allow.length;
         for ( i = 0;  i < n;  i++ ) {
            k    =  allow[i];
            $el  =  this.format( start + "_" + k,
                                 "radio",
                                 ( k === apply ),
                                 start );
         }   //   for i
      }
   };   // .opt.page.forming()



   FAdm.opt.page.formula  =  function ( access, apply, aware, amount ) {
      // Convert <div> into <input type='text'>
      // Precondition:
      //    access  -- element group selector
      //    apply   -- initial string, or false for password
      //    aware   -- visible number of characters
      //    amount  -- maximum number of characters
      // Postcondition:
      //    Text input element created and initialized
      // Uses:
      //    .opt.page.format()
      // 2011-09-08 PerfektesChaos@de.wikipedia
      var light  =  ( typeof( apply )  ===  "string" );
      var see    =  ( light ? "text" : "password" );
      var $el    =  this.format( "fA-" + see + "_" + access,
                                 see,
                                 apply );
      if ( $el.length ) {
         $el.attr( "size", aware );
         $el.attr( "maxlength", amount );
      }
   };   // .opt.page.formula()



   FAdm.opt.page.found  =  function ( access ) {
      // Show user default at <code />
      // Precondition:
      //    access  -- element group selector
      // Uses:
      //    >  .opt.*.obj
      //    >  .opt.page.$table
      //    .str.fromNum()
      //    jQuery.find()
      //    jQuery.text()
      // 2013-01-11 PerfektesChaos@de.wikipedia
      var v    =  FAdm.opt[ access ];
      var s;
      var $el;
      if ( v ) {
         v  =  v.obj;
         switch ( typeof( v ) ) {
            case "string" :
               s  =  "&quot;" + v + "&quot;";
               break;
            case "boolean" :
               s  =  ( v ? "true" : "false" );
               break;
            case "number" :
               s  =  FAdm.str.fromNum( v );
               break;
            default:
               s  =  false;
         }   // switch typeof(v)
         if ( s ) {
            $el  =  this.$table.find( "#fA-option_" + access );
            $el.text( s );
         }
      }
   };   // .opt.page.found()



};   // .bb.opt()
mediaWiki.libs.fileAdm.bb.opt( mediaWiki.libs.fileAdm, mediaWiki );
delete mediaWiki.libs.fileAdm.bb.opt;



//-----------------------------------------------------------------------



mediaWiki.libs.fileAdm.bb.portlet  =  function ( FAdm, mw ) {
   // Support portlet links
   // 2012-09-15 PerfektesChaos@de.wikipedia
   "use strict";
   if ( typeof FAdm.portlet !== "object" ) {
      FAdm.portlet  =  { };
   }



   FAdm.portlet.factory  =  function ( arglist ) {
      // Wrapper for mw.util.addPortletLink()
      // Precondition:
      //    arglist  -- object with definition
      //                >  .href     -- string, e.g. "http://..."
      //                >  .click    -- action, if .href not defined
      //                                either function or string
      //                >  .title    -- visible title
      //                >  .id       -- selector for portlet element
      //                >  .hint     -- tooltip
      //                >  .hotkey   -- hotkey character
      //                >  .target   -- target of link, or false
      //    action  -- click event handler
      // Postcondition:
      //    Portlet link created
      //    Returns false iff failed,  else <A> element  { dom, id }
      //    arglist modified
      //             < .portlet  -- DOM MW portlet element
      //             < .a        -- <A> element  { dom, id }
      // Uses:
      //    >  .str.call
      //    >  .str.script
      //    .portlet.fetch()
      //    mw.util.addPortletLink()
      // 2013-11-01 PerfektesChaos@de.wikipedia
      var domEl;
      var domNodes  =  this.fetch();
      var href      =  "#-";
      var link      =  ( typeof( arglist.href )  ===  "string" );
      var r         =  false;
      var re;
      if ( link ) {
         href  =  arglist.href;
      } else if ( typeof( arglist.click )  ===  "string" ) {
         href  =  FAdm.str.call + arglist.click;
         link  =  true;
      }
      if ( link ) {
         if ( href.indexOf( FAdm.str.script )  ===  0 ) {
            re  =  new RegExp( "\\bvoid *\\(" );
            if ( !  re.test( href ) ) {
               href  =  href + ";void(0);";
            }
         }
      }
      arglist.portlet  =  mw.util.addPortletLink( domNodes[0],
                                                  href,
                                                  arglist.title,
                                                  arglist.id,
                                                  arglist.hint,
                                                  arglist.hotkey,
                                                  domNodes[1] );
      if ( arglist.portlet ) {
         domEl  =  arglist.portlet;
         arglist.a  =  false;
         while ( domEl ) {
            if ( domEl.nodeName.toUpperCase() === "A" ) {
               arglist.a  =  { dom: domEl,
                               id:  arglist.id + ".a" };
               break;   // while
            } else if ( domEl.hasChildNodes() ) {
               domEl  =  domEl.firstChild;
            } else {
               break;   // while
            }
         }   // while
         if ( arglist.a ) {
            arglist.a.dom.setAttribute( "id",  arglist.a.id );
            if ( ! link ) {
               jQuery( "#" + arglist.a.id ).click(
                  function( event ) {
                     event.preventDefault();
                     arglist.click();
                  } );
            }
            if ( typeof( arglist.target )  ===  "string" ) {
               arglist.a.dom.target  =  arglist.target;
            }
            r  =  arglist.a;
         } else {
            arglist.portlet  =  false;
         }
      }
      return r;
   };   // .portlet.factory()



   FAdm.portlet.fetch  =  function () {
      // Fetch standard portlet location for any fileAdm tool link
      // Postcondition:
      //    Returns array[2]
      //            [0] selector ID of tool container
      //            [1] DOM elem or selector of next link to insert ahead
      // Uses:
      //    >< .portlet.$portlet
      //    mw.config.get()
      // 2012-08-30 PerfektesChaos@de.wikipedia
      var scope  =  "p-tb";
      var sel;
      var stick  =  "#t-whatlinkshere";
      var $li;
      if ( mw.config.get( "skin" )  ===  "vector" ) {
         if ( typeof( this.$portlet )  !==  "object" ) {
            sel  =  "#right-navigation";
            this.$portlet  =  jQuery(document).find( sel );
         }
         if ( this.$portlet.length ) {
            sel  =  "#p-cactions .menu li";
            $li  =  this.$portlet.find( sel );
            if ( $li.length ) {
               stick  =  $li.get( 0 );
            } else {
               stick  =  "#-";
            }
            // resources/jquery/jquery.collapsibleTabs.js
            scope  =  "p-cactions";
         }
      }
      return  [ scope, stick ];
   };   // .portlet.fetch()



   FAdm.portlet.flip  =  function ( arglist, apply ) {
      // Toggle link
      // Precondition:
      //    arglist  -- object with definition
      //                >  .a        -- DOM portlet link
      //                >  .off      -- variable link text: "Off"
      //                >  .on       -- variable link text: "On"
      //                >  .script   -- script name to be executed
      //                >  .varText  -- SPAN for variable link text
      //                 < .last     -- apply
      //    apply  -- true: show "Off", link to "On"
      //    Toggle link was created
      // Postcondition:
      //    Toggle link is changed
      // Uses:
      //    >  .str.call
      // 2011-10-06 PerfektesChaos@de.wikipedia
      var script;
      if ( arglist ) {
         if ( arglist.varText ) {
            script  =  arglist.script  + "("  +  ! apply  +  ");";
            arglist.a.dom.href           =  FAdm.str.call + script
                                            + "void(0);";
            arglist.varText.textContent  =  " " + ( apply ? arglist.off
                                                          : arglist.on );
            arglist.last                 =  apply;
         }
      }
   };   // .portlet.flip()



};   // .bb.portlet()
mediaWiki.libs.fileAdm.bb.portlet( mediaWiki.libs.fileAdm, mediaWiki );
delete mediaWiki.libs.fileAdm.bb.portlet;



//-----------------------------------------------------------------------



mediaWiki.libs.fileAdm.bb.queer  =  function ( FAdm, mw ) {
   // Questionable file description
   // 2012-09-15 PerfektesChaos@de.wikipedia
   "use strict";
   if ( typeof FAdm.queer !== "object" ) {
      FAdm.queer  =  { };
   }



   FAdm.queer.features  =  function ( advanced, assign ) {
      // Provide control box for single questionable file description
      // Precondition:
      //    advanced  -- no meaning here
      //    assign    -- true: set cookie; no meaning here
      //    Page is supposed to be a single file page during edit or view
      //    Desired checkbox state has to be set in advance
      // Postcondition:
      //    Control box is displayed
      // Uses:
      //    >  .queer
      //    >  .queer.textarea
      //    >  .queer.opts[]
      //    >< .str.action
      //    >< .queer.link.portlet
      //     < .queer.id
      //     < .queer.style
      //     < .queer.splash
      //     < .queer.start
      //     < .queer.submit
      //    .users.flag()
      //    .file.forge()
      //    .opt.control.formel()
      //    (.queer.fire)
      //    mw.config.get()
      //    .misc.message()
      // Remark: Used as event handler -- 'this' is not FAdm.queer
      // 2012-08-30 PerfektesChaos@de.wikipedia
      var i;
      var max;
      var option;
      var portlink;
      var s;
      var $form;
      var $ta;
      if ( assign && false ) {
         FAdm.users.flag( "Q", advanced );
      }
      if ( advanced || true ) {
         FAdm.queer.id      =  "fileAdm_Questionable";
         FAdm.queer.style   =  "border: solid 2px #FF0000; width: auto; "
                               + "background-color: #FFD9E2; "
                               + "padding: 5px; "
                               + "margin-top: 10px;";
         FAdm.queer.splash  =  "file.first('questionable')";
         FAdm.queer.start   =  "queer.fire()";
         FAdm.queer.submit  =  "queer.flash()";
         FAdm.file.forge( FAdm.queer );
         if ( FAdm.queer.$box ) {
            max  =  -1;
            if ( FAdm.queer.opts ) {
               max  =  FAdm.queer.opts.length;
            }
            $form  =  jQuery( "<form />" );
            for ( i = 0;  i < max;  i++ ) {
               option     =  FAdm.queer.opts[i];
               option.id  =  "fA-checkbox_" + i;
               if ( typeof( option.active ) !== "boolean" ) {
                  option.active  =  true;
               }
               if ( typeof( option.checked ) !== "boolean" ) {
                  option.checked  =  false;
               }
               $form.append( "<br>" );
               $form.append( FAdm.opt.control.formel( option ) );
               $form.append( option.key );
            }   // for i
            if ( ! FAdm.str.action ) {
               FAdm.str.action  =  mw.config.get( "wgAction" );
            }
            if ( FAdm.str.action === "view" ) {
               s    =  "<textarea id='fA-textarea'>";
               $ta  =  jQuery( s );
               //  "cols='" + queer.textarea[1] + "'"
               $ta.attr( "rows",  "'" + FAdm.queer.textarea[0] + "'" );
               $ta.attr( "style", "width: 95%;" );
               $form.append( $ta );
            }
            FAdm.queer.$content.append( $form );
            FAdm.misc.message( FAdm.queer.$box, "fileAdmQuestionable",
                               true );
            if ( FAdm.queer.link.portlet ) {
               portlink  =  FAdm.queer.link.portlet;
               portlink.parentNode.removeChild( portlink );
               FAdm.queer.link.portlet  =  false;
            }
         }   // $box
      }   // future limitation
   };   // .queer.features()



   FAdm.queer.feed  =  function ( apply ) {
      // Retrieve transclusion parameters
      // Precondition:
      //    apply  -- template string (not UTF-8) to be examined
      // Postcondition:
      //    Returns array with boolean state
      // Uses:
      //    >  .queer.opts
      //          >  .opts[].key
      // 2011-10-23 PerfektesChaos@de.wikipedia
      var i;
      var max  =  -1;
      var r    =  false;
      var re;
      if ( this.opts ) {
         max  =  this.opts.length;
         r    =  new Array( max );
      }
      for ( i = 0;  i < max;  i++ ) {
         re    =  new RegExp( "\\| *" + this.opts[i].key + " *",  "i" );
         r[i]  =  re.test( apply );
      }   // for i
      return r;
   };   // .queer.feed()



   FAdm.queer.fetch  =  function ( about, apply ) {
      // Retrieve state of transclusion or checkboxes into object
      // Precondition:
      //    about    -- origin of data
      //                0: checkboxes
      //                1: DOM/HTML page view
      //                2: URL parameter string
      //                3: examine request template in apply
      //                4: examine notified template in apply
      //    apply    -- string to be examined
      // Postcondition:
      //    .queer.opts[].checked is updated
      // Uses:
      //    >< .queer.opts
      //          >  .opts
      //          >  .opts[].id
      //           < .opts[].active
      //           < .opts[].checked
      //    .str.trimRight()
      //    .queer.feed()
      // 2011-10-12 PerfektesChaos@de.wikipedia
      var i;
      var liked;
      var max    =  -1;
      var num;
      var pars;
      var s;
      var $elem;
      if ( this.opts ) {
         max  =  this.opts.length;
      }
      for ( i = 0;  i < max;  i++ ) {
         if ( typeof( this.opts[i].checked )  !==  "boolean" ) {
            this.opts[i].checked  =  false;
         }
      }   // for i
      switch ( about ) {
         case 0 :   // checkboxes
            for ( i = 0;  i < max;  i++ ) {
               $elem  =  jQuery( "#" + this.opts[i].id );
               liked  =  $elem.prop( "checked" );
               this.opts[i].checked  =  liked;
            }   // for i
            break;
         case 1 :   // DOM/HTML page view
            for ( i = 0;  i < max;  i++ ) {
               $elem  =  jQuery( "#fileAdm_Qn_" + i );
               if ( $elem.length ) {
                  this.opts[i].active   =  false;
                  this.opts[i].checked  =  true;
               } else {
                  $elem  =  jQuery( "#fileAdm_Q_" + i );
                  if ( $elem.length ) {
                     this.opts[i].checked  =  true;
                  }
               }
            }   // for i
            break;
         case 2 :   // URL parameter
            pars  =  false;
            if ( typeof( apply )  ===  "string" ) {
               pars  =  apply.split( "/" );
            }
            if ( pars ) {
               for ( i = 0;  i < pars.length;  i++ ) {
                  s  =  pars[i];
                  if ( typeof( s )  ===  "string" ) {
                     s  =  FAdm.str.trimRight( s );
                     if ( s.length ) {
                        num  =  parseInt( s, 10 );
                        if ( num >= 0  &&  num < max ) {
                           this.opts[num].checked  =  true;
                        }
                     }
                  }
               }   // for i
            }
            break;
         case 3 :   // request template string
            pars  =  this.feed( apply );
            for ( i = 0;  i < max;  i++ ) {
               this.opts[i].checked  =  pars[i];
            }   // for i
            break;
         case 4 :   // notified template string
            pars  =  this.feed( apply );
            for ( i = 0;  i < max;  i++ ) {
               if ( pars[i] ) {
                  this.opts[i].active   =  false;
                  this.opts[i].checked  =  true;
               }
            }   // for i
            break;
      }   // switch about
   };   // .queer.fetch()



   FAdm.queer.fire  =  function () {
      // Prepare URL parameter for edit start
      // Postcondition:
      //    Editing of file description page started
      // Uses:
      //    >  .ia
      //    >  .queer.opts
      //    .queer.fetch()
      //    .edit.field()
      //    .queer.format()
      //    .queer.free()
      //    .file.fire()
      // Remark: Used as event handler -- 'this' is not FAdm.queer
      // 2013-01-12 PerfektesChaos@de.wikipedia
      var i;
      var got;
      var max;
      var option;
      var say;
      var story;
      FAdm.queer.fetch( 0, false );
      if ( FAdm.ia ) {
         got  =  FAdm.queer.format( FAdm.edit.field( false ) );
         if ( got ) {
            FAdm.edit.field( got[0] );
         }
      } else {
         max    =  -1;
         say    =  FAdm.queer.free();
         story  =  "questionable/";
         if ( FAdm.queer.opts ) {
            max  =  FAdm.queer.opts.length;
         }
         for ( i = 0;  i < max;  i++ ) {
            option  =  FAdm.queer.opts[i];
            if ( option.checked ) {
               if ( option.active ) {
                  story  =  story + i + "/";
               }   // checked
            }   // checked
         }   // for i
         if ( say ) {
            say    =  encodeURIComponent( say ).replace( /\//g, "%2F" )
                                               .replace( /\'/g, "%27" );
            story  =  story + "/*" + say + "*/";
         }
         FAdm.file.fire( story );
      }
   };   // .queer.fire()



   FAdm.queer.flash  =  function () {
      // Trigger insertion or filling questionable template by API
      // Postcondition:
      //    Page is updated by API if possible
      // Uses:
      //    >  .batch.watchQ
      //     < .queer.stuck
      //     < .batch.watch
      //    .queer.free()
      //    .batch.flash()
      //    .trans.bot.feeder()
      //    (.queer.format)
      // 2011-10-24 PerfektesChaos@de.wikipedia
      this.fetch( 0, false );
      this.stuck        =  this.free();
      FAdm.batch.watch  =  FAdm.batch.watchQ;
      FAdm.batch.flash( this.format, true );
//    .trans.bot.feeder();
   };   // .queer.flash()



   FAdm.queer.force  =  function ( adjust ) {
      // Insert or fill questionable template in file description page
      // Precondition:
      //    adjust   -- page content string (not UTF-8)
      // Postcondition:
      //    Return  false     -- nothing done
      //            array[3]  -- modified
      //                 [0] body string
      //                 [1] summary
      //                 [2] true: minor change
      //                 [3] .queer.subject
      // Uses:
      //    .queer.format()
      //    .users.fidelity()
      //    .trans.bot.feeder()
      // Remark: Used as event handler -- 'this' is not FAdm.queer
      // 2011-10-11 PerfektesChaos@de.wikipedia
      var r;
      r  =  FAdm.queer.format( adjust, true );
      if ( FAdm.users.fidelity() ) {
         FAdm.trans.bot.feeder();
      }
      return r;
   };   // .queer.force()



   FAdm.queer.format  =  function ( adjust, assign ) {
      // Insert or fill questionable template in file description page
      // Precondition:
      //    adjust  -- page content string (not UTF-8)
      //    assign  -- true    (insert at least empty template)
      //               string: URL edit parameter with checked data
      //               else:   use object properties
      // Postcondition:
      //    Return  false     -- nothing done
      //            array[5]  -- modified
      //                 [0] body string
      //                 [1] summary
      //                 [2] true: minor change
      //                 [3] .queer.subject
      //                 [4] string if watchlist
      // Uses:
      //    >  .queer.stamp
      //    >  .queer.stuck
      //    >  .queer.opts[].checked
      //    >  .queer.opts[].key
      //    >  .queer.specific
      //    >  .edit.summary0
      //    >  .queer.summary
      //    >  .batch.watchQ
      //    >  .queer.subject
      //    >< .queer.opts[].active
      //    .file.format()
      //    .edit.find()
      //    .queer.feed()
      //    .queer.fetch()
      //    .str.trimLeft()
      //    .str.trimRight()
      //    .str.escapePipes()
      // Remark: Used as event handler -- 'this' is not FAdm.queer
      // 2013-01-26 PerfektesChaos@de.wikipedia
      var basic    =  FAdm.file.format( adjust );
      var i;
      var jot;
      var light;
      var max      =  -1;
      var old      =  false;
      var option;
      var r        =  false;
      var say      =  false;
      var select;
      var story    =  "{{" + FAdm.queer.stamp;
      var suffix   =  adjust;
      var summary;
      var text;
      var wl;
      if ( basic ) {
         suffix  =  basic[0];
      }
      text  =  FAdm.edit.find( FAdm.queer.stamp, suffix );
      if ( text ) {
         old     =  FAdm.queer.feed( text[0] );
         suffix  =  text[1];
      }
      if ( typeof( assign )  ===  "string" ) {
         select  =  assign;
         jot     =  select.indexOf( "/*" );
         if ( jot >= 0 ) {
            say     =  select.substr( jot + 2 );
            say     =  say.substr( 0,  say. length - 2 );
            select  =  select.substr( 0, jot );
         }
         FAdm.queer.fetch( 2, select );
      } else {
         say  =  FAdm.queer.stuck;
         FAdm.queer.fetch( 1, false );
      }
      if ( FAdm.queer.opts ) {
         max  =  FAdm.queer.opts.length;
      }
      for ( i = 0;  i < max;  i++ ) {
         option  =  FAdm.queer.opts[i];
         if ( option.checked ) {
            if ( typeof( option.active )  !==  "boolean" ) {
               option.active  =  true;
            }
            if ( option.active ) {
               story  =  story + "|" + option.key;
            }
         }
      }   // for i
      if ( say ) {
         say    =  FAdm.str.trimRight( FAdm.str.trimLeft( say ) );
         story  =  story + "|" + FAdm.queer.specific + "="
                   +  FAdm.str.escapePipes( say );
      }
      story  =  story + "}}";
      /*
      if ( say ) {
         story  =  story + "\n\n" + say + " --~~~~\n\n";
      }
      */
      if ( suffix ) {
         story  =  story + "\n\n" + suffix;
      }
      if ( FAdm.str.trimRight( story )  !==
           FAdm.str.trimRight( adjust ) ) {
         light    =  true;
         summary  =  FAdm.queer.summary;
         wl       =  false;// 2013-05-05 false->
         if ( old ) {   // previous setting
            summary  =  FAdm.edit.summary0;
            for ( i = 0;  i < max;  i++ ) {
               if ( FAdm.queer.opts[i].checked !== old[i] ) {
                  light    =  false;
                  summary  =  FAdm.queer.summary;
                  wl       =  FAdm.batch.watchQ;
                  break;
               }   // checked
            }   // for i
         }
         r  =  [ story, summary, light, FAdm.queer.subject, wl ];
      }
      return r;
   };   // .queer.format()



   FAdm.queer.free  =  function () {
      // Fetch input from free text area
      // Postcondition:
      //    Return  non-empty content string, or false
      // Uses:
      //    .str.trimLeft
      //    .str.trimRight
      // 2011-09-28 PerfektesChaos@de.wikipedia
      var r  =  false;
      var s;
      var $free  =  jQuery( "#fA-textarea" );
      if ( $free.length ) {
         s  =  $free.val();
         if ( s.length ) {
            r  =  FAdm.str.trimRight( FAdm.str.trimLeft( s ) );
         }
      }
      return r;
   };   // .queer.free()



};   // .bb.queer()
mediaWiki.libs.fileAdm.bb.queer( mediaWiki.libs.fileAdm, mediaWiki );
delete mediaWiki.libs.fileAdm.bb.queer;



//-----------------------------------------------------------------------



mediaWiki.libs.fileAdm.bb.review  =  function ( FAdm, mw ) {
   // File review on single file description page
   // 2012-09-15 PerfektesChaos@de.wikipedia
   "use strict";
   if ( typeof FAdm.review !== "object" ) {
      FAdm.review  =  { };
   }



   FAdm.review.features  =  function ( advanced, assign ) {
      // Provide control box for file review on single file description
      // Precondition:
      //    advanced  -- true: advanced functionality (Review User)
      //    assign    -- true: set cookie
      //    Page is supposed to be a single file page during edit or view
      // Postcondition:
      //    Control box is displayed
      // Uses:
      //    >  .review.selTemplate
      //    >  .review.setup
      //    >  .review.signed
      //    >  .review.self
      //    >  .review.second
      //    >  .review.sucks
      //    >  .review.scope
      //    >  .review.scatter
      //     < .review.id
      //     < .review.style
      //     < .review.splash
      //     < .review.start
      //     < .review.submit
      //    .users.flag()
      //    .review.fine()
      //    .file.forge()
      //    .cat.file()
      //    (.file.first)
      //    (.file.fire)
      //    (.review.flash)
      //    mw.util.addCSS()
      //    .misc.message()
      // Remark: Used as event handler -- 'this' is not FAdm.review
      // 2012-09-15 PerfektesChaos@de.wikipedia
      var got     =  false;
      var lapsus;
      var mode;
      var show;
      var stuff;
      var $info, $ol;
      if ( assign ) {
         FAdm.users.flag( "R", advanced );
      }
      if ( advanced ) {
         show  =  FAdm.review.selTemplate
                  + "{ display: none !important; }";
//                + "{ display: block !important; }";
         mw.util.addCSS( show );
         got  = FAdm.review.fine();
      }
      if ( got ) {
         mode    =  got[0];
         lapsus  =  ( mode < -1 );
         FAdm.review.id     =  "fileAdm_Review";
         FAdm.review.style  =  "border: solid 2px; width: auto; "
                               +  ( lapsus  ?  "color: #FF0000; "
                                            :  "background-color: "
                                                          + "#B4EEB4; " )
                               +  "padding: 5px; margin-top: 10px;";
         if ( mode === 0  ||  mode === 1 ) {
            FAdm.review.splash  =  "file.first('approve')";
            FAdm.review.start   =  "file.fire('approve')";
            FAdm.review.submit  =  "review.flash()";
         } else {
            FAdm.review.splash  =  false;
            FAdm.review.start   =  false;
            FAdm.review.submit  =  false;
         }
         FAdm.file.forge( FAdm.review );
         if ( FAdm.review.$box ) {
            $info  =  jQuery( "<p />" );
            if ( mode > 0 ) {
               $ol  =  jQuery( "<ol />" );
               $ol.append( got[1] );
               if ( got[2] ) {
                  $ol.append( got[2] );
               }
               FAdm.review.$content.append( $ol );
            }
            switch ( mode ) {
               case  0 :
                  stuff  =  FAdm.review.setup;
                  break;
               case  1 :
                  stuff  =  FAdm.review.signed;
                  break;
               case -1 :
                  stuff  =  FAdm.review.self;
                  break;
               case  2 :
                  stuff  =  FAdm.review.second;
                  break;
               case -2 :
                  stuff  =  FAdm.review.sucks;
                  break;
               case -3 :
                  stuff  =  FAdm.review.scope;
                  break;
            }   // switch mode
            $info.text( stuff );
            FAdm.review.$content.append( $info );
            if ( ! FAdm.cat.file( false ) ) {
               $info  =  jQuery( "<p />" );
               $info.text( FAdm.review.scatter + "." );
               $info.attr( "style", "color: #FF0000;" );
               FAdm.review.$content.append( $info );
            }
            FAdm.misc.message( FAdm.review.$box,
                               "fileAdmReview",
                               false,
                               false );
                            // "width: 30em; right: 1em;"
         }   // $box
      }   // got
   };   // .review.features()



   FAdm.review.fine  =  function () {
      // Check whether file review is appropriate for this page
      // Precondition:
      //    Page is supposed to be a single file page during edit or view
      // Postcondition:
      //    Returns  false  -- not appropriate (Commons)
      //             array[2]
      //                  [0]   0 -- no review yet
      //                        1 -- first review done
      //                       -1 -- first review done by this user
      //                        2 -- second review done
      //                       -2 -- checking in progress
      //                       -3 -- not appropriate (not NoCommons)
      //                  [1]  <li> of first review
      //                  [2]  <li> of second review
      // Uses:
      //    >  .ns.sUser
      //    >  .users.w
      //    >  .guide.cats.review0
      //    >  .guide.cats.review1
      //    >  .guide.cats.review2
      //    >  .guide.cats.checking
      //    >  .ia
      //    >  .review.stamp
      //    >< .ns.sCat
      //    >< .file.cats
      //    .file.foreign()
      //    .guide.furnish()
      //    .guide.fulfil()
      //    .users.fetch()
      //    .edit.find()
      //    .edit.template.fetchParameter()
      //    mw.config.get()
      //    jQuery.isArray()
      //    mw.util.wikiUrlencode()
      // 2013-08-25 PerfektesChaos@de.wikipedia
      var gcs;
      var i;
      var lapsus;
      var n;
      var r;
      var re;
      var s;
      var scope1;
      var scope2;
      var signed;
      var story;
      var $user;
      var $user1;
      var $user2;
      var $users;
      r  =  ( ! FAdm.file.foreign() );
      if ( r ) {
         gcs     =  FAdm.guide.cats;
         lapsus  =  true;
         n       =  0;
         $user1  =  false;
         $user2  =  false;
         FAdm.guide.furnish();
         if ( ! FAdm.file.cats ) {
            FAdm.file.cats  =  mw.config.get( "wgCategories" );
         }
         if ( jQuery.isArray( FAdm.file.cats ) ) {
            n  =  FAdm.file.cats.length;
         }
         r  =  0;
         for ( i = 0;  i < n;  i++ ) {
            s      =  FAdm.file.cats[ i ];
            story  =  FAdm.ns.sCat + ":" + s;
            if ( FAdm.guide.fulfil( story, gcs.review0 ) ) {
               lapsus  =  false;   // NoCommons
            } else if ( FAdm.guide.fulfil( story, gcs.checking ) ) {
               r  =  -2;
               break;   // for i
            } else if ( ! r ) {
               if ( FAdm.guide.fulfil( story, gcs.review1 ) ) {
                  r  =  1;
               } else if ( FAdm.guide.fulfil( story, gcs.review2 ) ) {
                  r  =  2;
               }
            }
         }   // for i
         if ( ! n  &&  FAdm.ia ) {
            story   =  "/wiki/"
                       + mw.util.wikiUrlencode( gcs.review0[0] );
            scope1  =  "/wiki/"
                       + mw.util.wikiUrlencode( gcs.review1[0] );
            scope2  =  "/wiki/"
                       + mw.util.wikiUrlencode( gcs.review2[0] );
            n       =  document.links.length;
            for ( i = 0;
                  i < n   &&   ( ! r  ||  lapsus );
                  i++ ) {
               s  =  document.links[ i ].pathname;
               if ( s.indexOf( story )  ===  0 ) {
                  lapsus  =  false;
               //  gcs.checking
               } else if ( s.indexOf( scope1 )  ===  0 ) {
                  r  =  1;
               } else if ( s.indexOf( scope2 )  ===  0 ) {
                  r  =  2;
               }
            }   // for i
         }
         if ( lapsus ) {
            r  =  -3;
         }
         if ( r > 0 ) {
            $users  =  jQuery( "#fileAdm_Review-users" );
            if ( $users.length ) {
               $user   =  $users.find( "#fileAdm_Review-user1" );
               $user1  =  $user.clone();
               $user1  =  $user.clone();
               $user1.removeAttr( "id" );
               $user   =  $users.find( "#fileAdm_Review-user2" );
               $user2  =  $user.clone();
               $user2.removeAttr( "id" );
               $users.empty();
               if ( ! $user2.length ) {
                  if ( $user1.length ) {
                     $user  =  $user1.find( "a" );
                  }
                  if ( $user.length ) {
                     FAdm.users.fetch();
                     signed  =  $user.attr( "href" );
                     if ( signed ) {
                        FAdm.ns.fetch( true );
                        s   =  "/wiki/" + FAdm.ns.sUsers + ":"
                                        + FAdm.users.w + " ";
                        re  =  new RegExp( s, "i" );
                        if ( re.test( signed + " " ) ) {
                           r  =  -1;
                        }
                     }
                  } else {
                     r  =  false;
                  }
               }
/*
            } else if ( ia ) {   // yields plain syntax links
               var tmpl  =  edit.find( review.stamp , false );
               if ( tmpl ) {
                  story   =  tmpl[0];
                  s       =  edit.template.fetchParameter( story, 1 );
                  $user1  =  jQuery( "<li />" );
                  $user1.text( s );
                  if ( r === 2 ) {
                     s       =  edit.template.fetchParameter( story, 2 );
                     $user2  =  jQuery( "<li />" );
                     $user2.text( s );
                  }
               }
*/
            }
         }
         r  =  [ r, $user1, $user2 ];
      }
      return r;
   };   // .review.fine()



   FAdm.review.flash  =  function () {
      // Trigger insertion or filling approve template by API
      // Precondition:
      //    Page is permitted to be approved
      // Postcondition:
      //    Page is approved by API if permitted and possible
      // Uses:
      //    .batch.flash()
      //    (.review.force)
      // Remark: Used as event handler -- 'this' is not FAdm.review
      // 2011-09-18 PerfektesChaos@de.wikipedia
      FAdm.batch.flash( FAdm.review.force, true );
   };   // .review.flash()



   FAdm.review.force  =  function ( adjust ) {
      // Insert or fill approve template in file description page
      // Precondition:
      //    adjust   -- page content string (not UTF-8)
      // Postcondition:
      //    Return  false     -- nothing done
      //            array[3]  -- modified
      //                 [0] body string
      //                 [1] summary
      //                 [2] true: minor change
      //                 [3] .review.subject
      // Uses:
      //    .review.format()
      // Remark: Used as event handler -- 'this' is not FAdm.review
      // 2011-08-05 PerfektesChaos@de.wikipedia
      return  FAdm.review.format( adjust, true );
   };   // .review.force()



   FAdm.review.format  =  function ( adjust, approve ) {
      // Reformat file description page, insert or fill approve template
      // Precondition:
      //    adjust   -- page content string
      //    approve  -- true: approve if permitted and possible
      // Postcondition:
      //    Return  false     -- nothing done
      //            array[3]  -- modified
      //                 [0] body string
      //                 [1] summary
      //                 [2] true: minor change
      //                 [3] .review.subject
      // Uses:
      //    >  .file.stNoCommons
      //    >  .file.stNowCommons
      //    >  .ns.sUser
      //    >  .users.n
      //    >  .review.stamp
      //    >  .edit.summary0
      //    >  .review.summary1
      //    >  .review.summary2
      //    >  .review.subject
      //    .file.format()
      //    .edit.template.fetchRE()
      //    .users.fetch()
      //    .edit.formatPageTail()
      //    .edit.fold()
      //    .users.fair()
      //    .str.trimRight()
      // 2013-08-25 PerfektesChaos@de.wikipedia
      var got;
      var sign;
      var signed;
      var start;
      var story;
      var suffix;
      var swap;
      var label    =  approve;
      var mode     =  0;
      var r;
      var re;
      var seek;
      var shift;
      var summary;
      r      =  FAdm.file.format( adjust );
      shift  =  ( r ? r[0] : adjust );
      if ( label ) {
         re  =  FAdm.edit.template.fetchRE( FAdm.file.stNowCommons,
                                            true );
         re  =  new RegExp( re );
         if ( re.test( shift ) ) {
            label  =  false;
         } else {
            FAdm.users.fetch();
         }
      }
      if ( label ) {
         got     =  FAdm.edit.formatPageTail( shift );
         start   =  got[0];
         story   =  false;
         suffix  =  got[1];
         swap    =  "";
         got     =  FAdm.edit.fold( start, FAdm.review.stamp, true,
                                    false );
         if ( got[1] ) {
            sign    =  "[[" + FAdm.ns.sUser + ":" + FAdm.users.n;
            signed  =  "|" + sign + "|" + FAdm.users.n + "]] ~~~~~}}";
            story  =  got[2];
            start  =  got[3];
            if ( story ) {
               story  =   FAdm.users.fair( story );
               if ( story.indexOf( "~~~~" )  >  0 ) {
                  if ( story.indexOf( sign )  >  0 ) {
                     mode  =  -1;
                  }
               }
               if ( ! mode ) {
                  seek  =  ".*\\[\\[[A-Za-z]+:[^[}]+\\]\\].*";
                  re    =  new RegExp( seek + "\\|" + seek );
                  if ( re.test( story ) ) {
                     mode  =  -2;
                  } else {
                     re  =  new RegExp( seek );
                     if ( re.test( story ) ) {
                        mode   =  2;
                     }
                  }
               }
            } else {
               mode   =  1;
            }
         } else {
            mode  =  1;
         }
         if ( mode ) {
            if ( mode > 0 ) {
               swap  =  "{{" + FAdm.review.stamp;
               if ( mode === 2 ) {
                  swap  =  swap + story;
               }
               swap  =  swap + signed;
            }
            if ( start.length && swap.length ) {
               start  =  start + "\n\n";
            }
            start  =  start + swap + "\n";
            if ( suffix.length ) {
               start  =  start + "\n" + suffix + "\n";
            }
            shift  =  start + "\n";
         }
      }
      if ( shift !== adjust ) {
         summary  =  false;
         switch ( mode ) {
            case 1 :
               summary  =  FAdm.review.summary1;
               break;
            case 2 :
               summary  =  FAdm.review.summary2;
               break;
            default :
               if ( FAdm.str.trimRight( shift )  !==
                    FAdm.str.trimRight( adjust ) ) {
                  summary  =  FAdm.edit.summary0;
               }
         }   // switch mode
         r  =  [ shift,
                 summary,
                 ( mode > 0 ),
                 FAdm.review.subject ];
      }
      return r;
   };   // .review.format()



};   // .bb.review()
mediaWiki.libs.fileAdm.bb.review( mediaWiki.libs.fileAdm, mediaWiki );
delete mediaWiki.libs.fileAdm.bb.review;



//-----------------------------------------------------------------------



mediaWiki.libs.fileAdm.bb.str  =  function ( FAdm, mw ) {
   // String related
   // 2012-06-07 PerfektesChaos@de.wikipedia
   "use strict";
   if ( typeof FAdm.str !== "object" ) {
      FAdm.str  =  { page:  { scp: false }  };
   }
   if ( typeof FAdm.str.page !== "object" ) {
      FAdm.str.page  =  { scp: false };
   }



   FAdm.str.dateISO  =  function ( age ) {
      // Format date according to ISO 8601
      // Precondition:
      //    age  -- Date
      // Postcondition:
      //    Return string yyyy-mm-dd
      // Uses:
      //    .str.fromNum()
      // 2011-10-09 PerfektesChaos@de.wikipedia
      var r;
      var k  =      age.getFullYear()  *  10000
                +  (age.getMonth() + 1)  *  100
                +   age.getDate();
      var s  =  this.fromNum( k );
      r  =  s.substr( 0, 4 )  +  "-"  +
            s.substr( 4, 2 )  +  "-"  +
            s.substr( 6, 2 );
      return r;
   };   // .str.dateISO()



   FAdm.str.escapePipes  =  function ( adjust ) {
      // Escape pipe symbols '|' in text, but maintain links or templates
      // Precondition:
      //    adjust  -- base string
      // Postcondition:
      //    Return adjust with escaped pipes
      // Uses:
      //    this
      //    >< .str.reWSpaces
      // 2013-01-22 PerfektesChaos@de.wikipedia
      var r  =  adjust,
          s;
      if ( r.indexOf( "|" )  >=  0 ) {
         if ( ! this.reWSpaces ) {
            this.reWSpaces  =  new RegExp( "[\t\f ]+", "g" );
         }
         if ( ! this.rePipeTemplate ) {
            s                     =  "(\\{\\{[^}]+)\\|([^}]+\\}\\})";
            this.rePipeTemplate   =  new RegExp( s );
            this.rePipesTemplate  =  new RegExp( s, "g" );
         }
         r  =  r.replace( this.reWSpaces, " " )
                .replace( /\]/g, "\f" )
                .replace( /(\[\[[^|\f]+)\|([^\f]+\f\f)/g, "$1\t$2" );
         do {
            s  =  r;
            r  =  r.replace( this.rePipesTemplate, "$1\t$2" );
         } while ( s !== r );
         r  =  r.replace( /\|/g, "&#124;" )
                .replace( /\f/g, "]" )
                .replace( /\t/g, "|" );
      }
      return r;
   };   // .str.escapePipes()



   FAdm.str.fromNum  =  function ( adjust ) {
      // Format number as string
      // Precondition:
      //    adjust  -- base string
      // Postcondition:
      //    Return adjust as string
      // 2011-10-09 PerfektesChaos@de.wikipedia
      return adjust.toString();
   };   // .str.fromNum()



   FAdm.str.removeString  =  function ( adjust, apply ) {
      // Remove string from another string one or many times
      // Precondition:
      //    adjust  -- base string
      //    apply   -- string to be removed
      // Postcondition:
      //    Return modified string, or false
      // 2011-10-04 PerfektesChaos@de.wikipedia
      var i;
      var n  =  apply.length;
      var r  =  false;
      var s  =  adjust;
      while ( n ) {
         i  =  s.indexOf( apply );
         if ( i < 0 ) {
            break;   // while
         } else {
            r  =  s.substr( 0, i )  +  s.substr( i + n );
            s  =  r;
         }
      }   // while true
      return r;
   };   // .str.removeString()



   FAdm.str.substrEnd  =  function ( apply, amount ) {
      // Retrieve last characters from string like .slice(-n)
      //    or like Mozilla substr(-n, n)
      // Precondition:
      //    apply   -- string
      //    amount  -- position counted from end
      // Postcondition:
      //    Returns substring
      // IE does not support  substr(-n, n)
      // 2011-08-11 PerfektesChaos@de.wikipedia
      return apply.substr( apply.length - amount );
   };   // .str.substrEnd()



   FAdm.str.trimLeft  =  function ( adjust ) {
      // Strip off any leading whitespace
      // Precondition:
      //    adjust  -- string
      // Postcondition:
      //    Return trimmed string
      // 2011-07-24 PerfektesChaos@de.wikipedia
      var r  =  adjust;
      if ( r.length ) {
         while ( r.charCodeAt( 0 )  <=  32 ) {
            r  =  r.substr( 1 );
            if ( ! r.length ) {
               break;   // while
            }
         }   // while
      }
      return r;
   };   // .str.trimLeft()



   FAdm.str.trimRight  =  function ( adjust ) {
      // Strip off any leading whitespace
      // Precondition:
      //    adjust  -- string
      // Postcondition:
      //    Return trimmed string
      // 2011-07-24 PerfektesChaos@de.wikipedia
      var n  =  adjust.length;
      var r  =  adjust;
      if ( n > 0 ) {
         n--;
         while ( r.charCodeAt( n )  <=  32 ) {
            r  =  r.substr( 0, n );
            n--;
            if ( n < 0 ) {
               break;   // while
            }
         }   // while
      }
      return r;
   };   // .str.trimRight()



   FAdm.str.urlencode  =  function ( adjust ) {
      // Encode pagename with both namespace and a colon : in title
      // Precondition:
      //    adjust  -- string
      // Postcondition:
      //    Return encoded string
      // Uses:
      //    this
      //    .str.trimLeft()
      //    mw.util.wikiUrlencode()
      //    mw.config.get()
      // 2011-10-11 PerfektesChaos@de.wikipedia
      var i;
      var obj;
      var r;
      var start;
      var suffix;
      r  =  mw.util.wikiUrlencode( this.trimLeft( adjust ) );
      i  =  r.indexOf( ":" );
      if ( i > 0 ) {
         start   =  r.substr( 0, i );
         suffix  =  r.substr( i + 1 ).replace( /:/g, "%3A" );
         obj     =  mw.config.get( "wgNamespaceIds" );
         if ( typeof( obj[ start.toLowerCase() ]  ===  "number" ) ) {
            r  =  start + ":" + suffix;
         } else {
            r  =  start + "%3A" + suffix;
         }
      }
      return r;
   };   // .str.urlencode()



};   // .bb.str()
mediaWiki.libs.fileAdm.bb.str( mediaWiki.libs.fileAdm, mediaWiki );
delete mediaWiki.libs.fileAdm.bb.str;



//-----------------------------------------------------------------------



mediaWiki.libs.fileAdm.bb.trans  =  function ( FAdm, mw ) {
   // Transfer to commons management
   // 2012-09-15 PerfektesChaos@de.wikipedia
   "use strict";
   if ( typeof FAdm.trans !== "object" ) {
      FAdm.trans  =  {  bot:  { },
                        idle: { },
                        vsn:  { }  };
   }
   if ( typeof FAdm.trans.bot !== "object" ) {
      FAdm.trans.bot  =  { };
   }
   if ( typeof FAdm.trans.idle !== "object" ) {
      FAdm.trans.idle  =  { };
   }
   if ( typeof FAdm.trans.vsn !== "object" ) {
      FAdm.trans.vsn  =  { };
   }


   FAdm.trans.features  =  function ( advanced, assign ) {
      // Make control box for file transfer on single file description
      // Precondition:
      //    advanced  -- true: advanced functionality (sysop / CTB group)
      //    assign    -- true: set cookie
      //    Page is supposed to be a single file page during edit or view
      // Postcondition:
      //    Control box is displayed
      // Uses:
      //    >  .file.type
      //    >  .trans.sucks
      //    >  .str.action
      //    >  .$content
      //    >  .trans.idle.say
      //    >  .str.call
      //    >  .batch.styleButton
      //    >  .trans.idle.id
      //    >  .trans.idle.sleep
      //    >  .trans.bot.pageName
      //     < .trans.id
      //     < .trans.style
      //     < .trans.splash
      //     < .trans.start
      //     < .trans.submit
      //     < .trans.bot.post
      //    .users.flag()
      //    .file.forge()
      //    .trans.idle.fetch()
      //    .trans.vsn.find()
      //    .batch.fetch()
      //    (.file.first)
      //    (.file.fire)
      //    (.trans.idle.flash)
      //    (.trans.bot.found)
      //    .misc.message()
      // Remark: Used as event handler -- 'this' is not FAdm.trans
      // 2012-08-30 PerfektesChaos@de.wikipedia
      var layer;
      var lazy     =  ( FAdm.file.type === "transfix"  ||
                        FAdm.file.type === "transnot"  ||
                        FAdm.file.type === "trash" );
      var say;
      var $button;
      var $err;
      var $flash;
      var $idle;
      if ( assign ) {
         FAdm.users.flag( "T", advanced );
      }
      if ( advanced ) {
         layer  =  ( FAdm.str.action === "view" );
         FAdm.trans.id      =  "fileAdm_Transfer";
         FAdm.trans.style   =  "border: solid 2px #0000FF; width: auto; "
                          + "background-color: #DDDDFF; "
                          + "padding: 5px; margin-top: 10px;";
         if ( ! lazy ) {
            FAdm.trans.splash  =  "file.first('transfer')";
            FAdm.trans.start   =  "file.fire('transfer')";
            FAdm.trans.submit  =  "trans.flash()";
         }
         FAdm.file.forge( FAdm.trans );
         if ( lazy ) {
            say  =  false;
            if ( FAdm.file.type === "transnot" ) {
               say  =  FAdm.trans.sucks;
            } else if ( FAdm.file.type === "trash" ) {
               say  =  "NowCommons";
            }
            if ( say ) {
               $err  =  jQuery( "<strong />" );
               if ( $err.length ) {
                  $err.attr( "style",
                             "color: #FF0000; font-weight: bold" );
                  $err.text( say );
                  FAdm.trans.$content.append( $err );
               }
            } else if ( layer  &&  FAdm.file.type === "transfix" ) {
               $button  =  jQuery( "<p />" );
               $flash   =  jQuery( "<a />" );
               $idle    =  jQuery( "<span />" );
               $flash.text( FAdm.trans.idle.say );
               $flash.attr( "href",
                            FAdm.str.call + "trans.idle.flash()" );
               $flash.attr( "style", FAdm.batch.styleButton );
               $button.append( $flash );
               $idle.attr( "id", FAdm.trans.idle.id );
               $idle.text( " " + FAdm.trans.idle.sleep );
               $idle.css( "display", "none" );
               $button.append( $idle );
               FAdm.trans.$content.append( $button );
               FAdm.trans.idle.fetch();
            }
            if ( FAdm.file.type === "trash" ) {
               FAdm.trans.vsn.find();
            }
         }
         FAdm.misc.message( FAdm.trans.$box, "fileAdmTransfer", true );
         FAdm.trans.bot.post  =  false;
         FAdm.batch.fetch( FAdm.trans.bot.pageName,
                           FAdm.trans.bot.found );
      }
   };   // .trans.features()



   FAdm.trans.flash  =  function () {
      // Trigger insertion or filling CTB template by API
      // Precondition:
      //    Page is permitted to be transferred
      // Postcondition:
      //    Page is marked by API if permitted and possible
      // Uses:
      //    >  .batch.watchT
      //     < .batch.watch
      //    .batch.flash()
      //    (.trans.force)
      // 2011-10-24 PerfektesChaos@de.wikipedia
      FAdm.batch.watch  =  FAdm.batch.watchT;
      FAdm.batch.flash( this.force, true );
   };   // .trans.flash()



   FAdm.trans.flop  =  function ( already ) {
      // Check whether current description page is both NoCommons and CTB
      // Precondition:
      //    already  -- false: detect from categories;  true: display now
      //    Current page is member of NoCommons
      // Postcondition:
      //    Returns true iff conflict -- page supposed to be transferred
      //    Warning box is displayed
      // Uses:
      //    >  .guide.cats.transfer
      //    >  .guide.cats.transit
      //    >  .guide.cats.transmit
      //    >  .guide.cats.transfix
      //    >  .str.sayConflict
      //    >  .trans.sayNo
      //    >< .file.cats
      //    mw.config.get()
      //    .misc.message()
      // 20112-08-30 PerfektesChaos@de.wikipedia
      var gcs;
      var i;
      var r      =  false;
      var s;
      var style;
      var $box;
      var $head;
      var $info;
      if ( already ) {
         r  =  true;
      } else {
         gcs  =  FAdm.guide.cats;
         if ( ! gcs ) {
            FAdm.file.cats  =  mw.config.get( "wgCategories" );
            gcs             =  FAdm.guide.cats;
         }
         for ( i = 0;  i < gcs.length;  i++ ) {
            s  =  gcs[i].title;
            if ( FAdm.guide.fulfil( s, gcs.transfer ) ) {
               r   =  true;
            } else if ( FAdm.guide.fulfil( s, gcs.transit ) ) {
               r   =  true;
            } else if ( FAdm.guide.fulfil( s, gcs.transmit ) ) {
               r   =  true;
            } else if ( FAdm.guide.fulfil( s, gcs.transfix ) ) {
               r   =  true;
            }
            if ( r ) {
               break;   // for i
            }
         }   // for i
      }
      if ( r ) {
         style  =  "color: #FF0000; border: solid 2px; width: auto; "
                   + "padding: 5px; margin-top: 10px;";
         $box   =  jQuery( "<div />" );
         $head  =  jQuery( "<strong />" );
         $info  =  jQuery( "<span />" );
         $head.text( FAdm.str.sayConflict );
         $box.append( $head );
         $info.text( " * " + this.sayNo );
         $box.append( $info );
         FAdm.misc.message( $box, "fileAdmTransferNoCommons", true );
      }
      return r;
   };   // .trans.flop()



   FAdm.trans.force  =  function ( adjust ) {
      // Insert or fill CTB template in file description page
      // Precondition:
      //    adjust  -- page content string (not UTF-8)
      // Postcondition:
      //    Return  false     -- nothing done
      //            array[3]  -- modified
      //                 [0] body string
      //                 [1] summary
      //                 [2] true: minor change
      //                 [3] .trans.subject
      // Uses:
      //     < .str.page.content
      //    .trans.format()
      //    .trans.bot.feeder()
      // Remark: Used as event handler -- 'this' is not FAdm.trans
      // 2011-10-11 PerfektesChaos@de.wikipedia
      var r;
      FAdm.str.page.content  =  adjust;
      r                      =  FAdm.trans.format( true );
      if ( r ) {
         FAdm.str.page.content  =  r[0];
      }
      FAdm.trans.bot.feeder();
      return r;
   };   // .trans.force()



   FAdm.trans.format  =  function ( approve ) {
      // Reformat file description, insert or replace transfer template
      // Precondition:
      //    approve  -- true: transfer by bot if permitted and possible
      //    advance  -- true: call request queue
      // Postcondition:
      //    Return  false     -- nothing done
      //            array[3]  -- modified
      //                 [0] body string
      //                 [1] summary
      //                 [2] true: minor change
      //                 [3] .trans.subject
      //                 [4] string if watchlist
      // Uses:
      //    >  .file.stNoCommons
      //    >  .file.stNowCommons
      //    >  .trans.stable
      //    >  .trans.suitable
      //    >  .trans.stamp
      //    >  .trans.summary
      //    >  .batch.watchT
      //    >  .edit.summary0
      //    >  .trans.subject
      //    >< .str.page.title
      //    >< .str.page.content
      //     < .trans.bot.commons
      //    .file.format()
      //    .edit.template.fetchRE()
      //    .trans.flop()
      //    .edit.fold()
      //    .edit.find()
      //    .edit.template.fetchParameter()
      //    mw.config.get()
      // 2011-11-30 PerfektesChaos@de.wikipedia
      var r;
      var got;
      var label    =  true;
      var mode     =  0;
      var re       =  FAdm.edit.template.fetchRE( FAdm.file.stNoCommons,
                                                  true );
      var shift    =  FAdm.str.page.content;
      var splash;
      var summary;
      var wl;
      r  =  FAdm.file.format( FAdm.str.page.content );
      if ( r ) {
         shift  =  r[0];
         mode   =  1;
      }
      re  =  new RegExp( re );
      if ( re.test( shift ) ) {
         this.flop( true );
         label  =  false;
      } else {
         re  =  FAdm.edit.template.fetchRE( FAdm.file.stNowCommons,
                                            true );
         re  =  new RegExp( re );
         if ( re.test( shift ) ) {
            label  =  false;
         }
      }
      this.bot.commons  =  false;
      if ( label && approve ) {
         got  =  FAdm.edit.fold( shift, this.stable, false, false );
         if ( got ) {
            shift             =  got[3];
            this.bot.commons  =  true;
         }
         got  =  FAdm.edit.find( this.suitable, shift );
         if ( got ) {
            splash  =  FAdm.edit.template.fetchParameter( got[0], 2 );
            shift   =  got[1];
            if ( splash ) {
               this.bot.commons  =  splash;
            } else {
               this.bot.commons  =  true;
            }
         }
      }
      if ( label ) {
         got  =  FAdm.edit.fold( shift, this.stamp, false, true );
         if ( got ) {
            splash  =  FAdm.edit.template.fetchParameter( got[0], 1 );
            shift   =  got[3];
            if ( splash ) {
               this.bot.commons  =  splash;
            } else {
               this.bot.commons  =  true;
            }
         } else if ( approve ) {
            this.bot.commons  =  true;
         }
         if ( this.bot.commons ) {
            if ( typeof( this.bot.commons )  ===  "string" ) {
               splash  =  "|1=" + this.bot.commons;
            } else {
               splash  =  "";
               if ( ! FAdm.str.page.title ) {
                  FAdm.str.page.title  =  mw.config.get( "wgTitle" );
               }
               this.bot.commons  =  FAdm.str.page.title;
            }
            shift  =  "{{" + this.stamp + splash + "}}\n\n" + shift;
         }
      }
      if ( shift !== FAdm.str.page.content ) {
         summary  =  "";
         wl       =  false;// 2013-05-05 false->
         if ( this.bot.commons ) {
            summary  =  this.summary;
            wl       =  FAdm.batch.watchT;
            mode     =  2;
         } else if ( FAdm.str.trimRight( shift )  !==
                     FAdm.str.trimRight( FAdm.str.page.content ) ) {
            summary  =  FAdm.edit.summary0;
         }
         FAdm.str.page.content  =  shift;
         r  =  [ FAdm.str.page.content,
                 summary,
                 ( mode > 0 ),
                 this.subject,
                 wl ];
      }
      return r;
   };   // .trans.format()



   FAdm.trans.bot.feed  =  function () {
      // Check whether desired file transfer matches bot queue content
      // Precondition:
      //    Current page: file description, maybe transferring to commons
      //    API query for queue content returned
      // Postcondition:
      //    API update of queue items equipped and started, if meaningful
      // Uses:
      //    >  .str.page.content
      //    >  .queer.quest
      //    >  .trans.stamp
      //    >  .str.page.name
      //    >  .trans.bot.queue
      //    >< .str.page.title
      //    >< .trans.bot.commons
      //     < .trans.bot.post
      //     < .trans.bot.discard
      //     < .trans.bot.update
      //    .trans.bot.finish()
      //    .edit.template.fetchRE()
      //    .edit.template.fetchParameter()
      //    .batch.faith()
      //    .batch.fetch()
      //    (.trans.bot.furnish)
      //    mw.config.get()
      //    mw.html.escape()
      // 2012-01-08 PerfektesChaos@de.wikipedia
      var got;
      var i;
      var k;
      var m;
      var mode   =  false;
      var n;
      var re;
      var seek;
      var shift;
      var split;
      var start;
      var stop;
      this.post  =  false;
      if ( this.finish ) {
         this.finish( true );
      }
      if ( ! FAdm.str.page.title ) {
         FAdm.str.page.title  =  mw.config.get( "wgTitle" );
      }
      if ( this.commons ) {
         mode  =  1;
         if ( typeof( this.commons )  !==  "string" ) {
            this.commons  =  FAdm.str.page.title;
         }
      }
      if ( FAdm.str.page.content ) {
         re  =  FAdm.edit.template.fetchRE( FAdm.queer.quest, true );
         re  =  new RegExp( re );
         if ( re.test( FAdm.str.page.content ) ) {
            mode  =  -1;
         }
         if ( ! this.commons  &&  ! mode ) {
            re   =  FAdm.edit.template.fetchRE( FAdm.trans.stamp, false )
                    + "[^}]*}}";
            re   =  new RegExp( re );
            got  =  re.exec( FAdm.str.page.content );
            if ( got !== null ) {
               this.commons  =
                          FAdm.edit.template.fetchParameter( got[0], 1 );
               mode  =  2;
            }
            if ( ! this.commons ) {
               this.commons  =  FAdm.str.page.title;
            }
         }
      }
      if ( typeof( this.queue )  ===  "string" ) {
         seek   =  mw.html.escape( FAdm.str.page.title );
         start  =  "<request local=\"";
         split  =  "\" commons=\"";
         stop   =  "\" />";
         shift  =  false;
         i  =  this.queue.indexOf( seek );
         if ( i > 16 ) {
            k  =  -2;
            n  =  seek.length;
            m  =  i + n + 11;
            if ( this.queue.slice( i - 16,  i )   ===   start    &&
                 this.queue.slice( i + n,  m )   ===   split ) {
               k  =  this.queue.indexOf( stop, m );
               if ( k > m ) {
                  shift  =  this.queue.slice( m, k );
                  if ( this.commons ) {
                     if ( this.commons !== shift ) {   // update
                        mode  =  0;
                     }
                  }
               }
            }
         }
         if ( typeof( mode )  ===  "number" ) {
            FAdm.batch.faith();
            start  =  start + seek + split;
            if ( mode <= 0 ) {
               if ( shift ) {
                  this.discard  =  start + shift + stop;
               }
            }
            if ( mode >= 0 ) {
               this.update  =  start
                                    + mw.html.escape( this.commons )
//                                  + commons.replace( /\"/g,  "&#34;" )
                                    + stop;
            }
            FAdm.batch.fetch( this.pageName, this.furnish );
         }
      }
   };   // .trans.bot.feed()



   FAdm.trans.bot.feeder  =  function () {
      // Append request entry on bot page, or delete if not appropriate
      // Precondition:
      //    Current page is description, maybe transferring to commons
      //    API query for queue should have been launched
      // Postcondition:
      //    API query for queue has been launched
      // Uses:
      //    >  .trans.bot.queue
      //    >  .str.page.content
      //    >  .trans.bot.pageName
      //     < .trans.bot.post
      //    .trans.bot.feed()
      //    .batch.fetch()
      //    .batch.feed()
      //    (.trans.bot.feeder)
      // Remark: Used as event handler -- 'this' is not FAdm.trans.bot
      // 2011-10-11 PerfektesChaos@de.wikipedia
      if ( typeof( FAdm.trans.bot.queue )  ===  "string"   &&
           typeof( FAdm.str.page.content )  ===  "string" ) {
         FAdm.trans.bot.feed();
      } else {
         if ( ! FAdm.trans.bot.queue ) {
            FAdm.trans.bot.queue  =  true;
            FAdm.trans.bot.post   =  FAdm.trans.bot.feeder;
            FAdm.batch.fetch( FAdm.trans.bot.pageName,
                              FAdm.trans.bot.found );
         }
         if ( ! FAdm.str.page.content ) {
            FAdm.str.page.content  =  true;
            FAdm.batch.feed( FAdm.trans.bot.feeder );
         }
      }
   };   // .trans.bot.feeder()



   FAdm.trans.bot.find  =  function ( advanced, assign ) {
      // Start save button exercises on interactive edit
      // Precondition:
      //    advanced  -- true: advanced functionality (sysop / CTB group)
      //    assign    -- true: set cookie
      //    Interactive mode assumed
      // Uses:
      //    .trans.bot.finish()
      //    .users.flag()
      // Remark: Used as event handler -- 'this' is not FAdm.trans.bot
      // 2013-01-07 PerfektesChaos@de.wikipedia
      if ( advanced ) {
         FAdm.trans.bot.finish( false );
      }
      if ( assign ) {
         FAdm.users.flag( "T", advanced );
      }
   };   // .trans.bot.find()



   FAdm.trans.bot.finish  =  function ( able ) {
      // Handle save button hook exercises on interactive edit
      // Precondition:
      //    able  -- true: execute save action,  false: disable button
      //    Interactive mode assumed
      // Uses:
      //    >  .ia
      //    >  .ia.$editform
      //    >  .str.call
      //    >  .trans.bot.save
      //     < .trans.bot.$xSave
      //    edit.form()
      //    button.click()
      //    (.trans.bot.finished)
      // Remark: Used as event handler -- 'this' is not FAdm.trans.bot
      // 2011-10-23 PerfektesChaos@de.wikipedia
      var button;
      var $button;
      if ( able ) {
         // DOM, not hooked by editwarner:
         button  =  document.getElementById( "wpSave" );
         if ( button !== null ) {
            button.click();
         }
      } else {   // editing
         if ( ! FAdm.ia ) {   // initialize
            FAdm.edit.form();
         }
         if ( FAdm.ia ) {
            $button  =  FAdm.ia.$editform.find( "#wpSave" );
            if ( $button.length ) {
               FAdm.trans.bot.$xSave  =  jQuery( "<a />" );
               FAdm.trans.bot.$xSave.attr( "href",
                                           FAdm.str.call
                                           + "trans.bot.finished()" );
               FAdm.trans.bot.$xSave.attr( "style",
                                           "border: solid 2px;"
                                           + "border-color: #D0D0FF "
                                                         + "#D0D0FF "
                                                         + "#6060FF "
                                                         + "#6060FF;"
                                           + "padding: 1px 2px;" );
               FAdm.trans.bot.$xSave.text( FAdm.trans.bot.save );
               FAdm.trans.bot.$xSave.insertAfter( $button );
               $button.css( "display", "none" );
            }
         }
      }
   };   // .trans.bot.finish()



   FAdm.trans.bot.finished  =  function () {
      // Postprocess interactive CTB file edit against bot queue and save
      // Precondition:
      //    Special save button has been clicked
      // Postcondition:
      //    CTB file transfer queue is
      // Uses:
      //    >  .trans.bot.$xSave
      //    >  .str.page.content
      //    .trans.format()
      //    .edit.finalize()
      //    .trans.bot.feeder()
      // 2011-10-11 PerfektesChaos@de.wikipedia
      var change;
      this.$xSave.attr( "href", null );
      this.$xSave.attr( "style",
                        "border: solid 1px #0000FF; "
                        + "padding: 1px 2px;"
                        + "background-color: #D0D0FF" );
      FAdm.edit.field( false );
      if ( typeof( FAdm.str.page.content )  ===  "string" ) {
         change  =  FAdm.trans.format( false );
         FAdm.edit.finalize( change );
      }
      this.feeder();
   };   // .trans.bot.finished()



   FAdm.trans.bot.found  =  function ( arrived ) {
      // Postprocess file entry on bot queue page after ajax request
      // Precondition:
      //    arrived  -- JSON result of ajax query for
      // Postcondition:
      //    Queue page content is stored,  trans.bot.post may be called
      // Uses:
      //    >  .trans.bot.post
      //     < .trans.bot.queue
      //     < .trans.bot.rvtime
      //    (.trans.bot.post)
      // Remark: Used as event handler -- 'this' is not FAdm.trans.bot
      // 2011-10-11 PerfektesChaos@de.wikipedia
      var query  =  ( typeof( arrived )  ===  "object" );
      var sid;
      if ( query ) {
         query  =  arrived.query;
         if ( query ) {
            sid  =  query.pageids[0];
            if ( sid.charCodeAt( 0 )  !==  45 ) {   // '-'
               query  =  query.pages[ sid ];
               if ( query ) {
                  query  =  query.revisions;
                  if ( query ) {
                     query  =  query[ "0" ];
                     if ( query ) {
                        FAdm.trans.bot.queue   =  query[ "*" ];
                        FAdm.trans.bot.rvtime  =  query.timestamp;
                     }
                  }
               }
            }   // for i
            if ( FAdm.trans.bot.post ) {
               FAdm.trans.bot.post();
            }
         }
      }
   };   // .trans.bot.found()



   FAdm.trans.bot.furnish  =  function ( arrived ) {
      // Update bot transfer queue
      // Precondition:
      //    arrived  -- JSON result of ajax query for
      //    API query for queue content most recently updated
      // Postcondition:
      //    API update for queue content launched
      // Uses:
      //    >  .trans.bot.queue
      //    >  .trans.bot.discard
      //    >  .trans.bot.update
      //    >  .trans.bot.rvtime
      //    >  .batch.watchT
      //    >< .str.page.name
      //    >< .str.page.title
      //     < .trans.bot.post
      //     < .batch.page
      //     < .batch.rvtime
      //     < .batch.watch
      //    .trans.bot.found()
      //    .str.removeString()
      //    .str.trimRight()
      //    .batch.force()
      //    mw.config.get()
      //    .misc.message()
      // Remark: Used as event handler -- 'this' is not FAdm.trans.bot
      // 2012-08-30 PerfektesChaos@de.wikipedia
      var change;
      var say     =  false;
      var s;
      FAdm.trans.bot.found( arrived );
      FAdm.trans.bot.post  =  false;
      if ( FAdm.trans.bot.discard ) {
         s  =  FAdm.str.removeString( FAdm.trans.bot.queue,
                                      FAdm.trans.bot.discard );
         if ( s ) {
            FAdm.trans.bot.queue  =  s;
            say                   =  "-";
         }
      }
      if ( FAdm.trans.bot.update ) {
         s  =  FAdm.str.trimRight( FAdm.trans.bot.queue );
         if ( s.indexOf( FAdm.trans.bot.update )  <  0 ) {
            FAdm.trans.bot.queue  =  s + "\n\n"
                                     + FAdm.trans.bot.update + "\n";
            if ( say ) {
               say  =  "~";
            } else {
               say  =  "+";
            }
         }
      }
      if ( say ) {
         if ( ! FAdm.str.page.name ) {
            FAdm.str.page.name  =  mw.config.get( "wgPageName" );
         }
         if ( ! FAdm.str.page.title ) {
            FAdm.str.page.title  =  mw.config.get( "wgTitle" );
         }
         change  =  [ FAdm.trans.bot.queue,
                      say + " [[" + FAdm.str.page.name
                            + "|" + FAdm.str.page.title + "]]",
                      false ];
         FAdm.batch.page    =  FAdm.trans.bot.pageName;
         FAdm.batch.rvtime  =  FAdm.trans.bot.rvtime;
         FAdm.batch.watch   =  FAdm.batch.watchT;
         FAdm.batch.force( change, false );
      }
      FAdm.misc.message();
   };   // .trans.bot.furnish()



   FAdm.trans.idle.fetch  =  function () {
      // Query whether current page has been unchanged for some days
      // Precondition:
      //    Current page is file description with transfer to commons
      // Postcondition:
      //    API query has been launched
      // Uses:
      //    >< .str.page.name
      //    >< .batch.api
      //     < .trans.idle.query
      //    .str.dateISO()
      //    (.trans.idle.found)
      //    mw.config.get()
      //    mw.util.wikiScript()
      //    jQuery.getJSON()
      // 2011-10-10 PerfektesChaos@de.wikipedia
      var timer  =  new Date();
      timer.setTime( timer.getTime()  -  3 * 86400 * 1000 );
      if ( ! FAdm.str.page.name ) {
         FAdm.str.page.name  =  mw.config.get( "wgPageName" );
      }
      if ( ! FAdm.batch.api ) {
         FAdm.batch.api  =  mw.util.wikiScript( "api" );
      }
      this.query  =  { action:       "query",
                       prop:         "revisions",
                       rvprop:       "content|timestamp",
                       rvlimit:      1,
                       indexpageids: true,
                       titles:       FAdm.str.page.name,
                       format:       "json" };
      this.query.rvend  =  FAdm.str.dateISO( timer )  +  "T00:00:00Z";
      jQuery.getJSON( FAdm.batch.api,
                      this.query,
                      this.found );
   };   // .trans.idle.fetch()



   FAdm.trans.idle.flash  =  function () {
      // Update request entry on bot page
      // Precondition:
      //    Page is permitted to be transferred
      // Postcondition:
      //    Request queue update is launched
      // Uses:
      //     < .trans.bot.finish
      //    .trans.bot.feeder()
      // Remark: Used as event handler -- 'this' is not FAdm.trans.idle
      // 2011-10-11 PerfektesChaos@de.wikipedia
      FAdm.trans.bot.finish  =  false;
      FAdm.trans.bot.feeder();
   };   // .trans.idle.flash()



   FAdm.trans.idle.found  =  function ( arrived ) {
      // Postprocess page revision list after ajax request
      // Precondition:
      //    arrived  -- JSON result of ajax query for page revisions
      // Postcondition:
      //    Invisible remark on idle page is displayed.
      // Uses:
      //    >  .trans.idle.id
      // Remark: Used as event handler -- 'this' is not FAdm.trans.idle
      // 2011-12-30 PerfektesChaos@de.wikipedia
      var query  =  ( typeof( arrived )  ===  "object" );
      var lazy   =  false;
      var $idle;
      if ( query ) {
         query  =  arrived.query;
         if ( query ) {
            query  =  query.pages[ query.pageids[ 0 ] ];
            if ( query ) {
               query  =  query.revisions;
               if ( query ) {
                  lazy   =  ( query.length === 0 );
               }
            }
         }
      }
      if ( lazy ) {
         $idle  =  jQuery( "#" + FAdm.trans.idle.id );
         if ( $idle.length ) {
            $idle.attr( "style", "color:#FF0000; font-style:italic;" );
         }
      }
   };   // .trans.idle.found()



   FAdm.trans.vsn.find  =  function () {
      // Check for multiple versions of image
      // Precondition:
      //    File description page contains NowCommons template/category.
      // Postcondition:
      //    Query is launched
      // Uses:
      //    >  .str.page.name
      //    >< .batch.api
      //     < .trans.vsn.query
      //    mw.config.get()
      //    mw.util.wikiScript()
      //    jQuery.getJSON()
      //    (.trans.vsn.found)
      // 2011-12-30 PerfektesChaos@de.wikipedia
      if ( ! FAdm.str.page.name ) {
         FAdm.str.page.name  =  mw.config.get( "wgPageName" );
      }
      if ( ! FAdm.batch.api ) {
         FAdm.batch.api  =  mw.util.wikiScript( "api" );
      }
      this.query  =  { action:       "query",
                       prop:         "imageinfo",
                       iilimit:      2,
                       indexpageids: true,
                       titles:       FAdm.str.page.name,
                       format:       "json" };
      jQuery.getJSON( FAdm.batch.api,
                      this.query,
                      this.found );
   };   // .trans.vsn.find()



   FAdm.trans.vsn.found  =  function ( arrived ) {
      // Postprocess file description page after ajax request
      // Precondition:
      //    arrived  -- JSON result of ajax query for multiple version
      // Postcondition:
      //    Multiple version note on page is displayed.
      // Uses:
      //    >  .trans.vsn.say
      //    >  .trans.$content
      //    >  .trans.vsn.sel
      //     < .file.lone
      // Remark: Used as event handler -- 'this' is not FAdm.trans.vsn
      // 2011-12-30 PerfektesChaos@de.wikipedia
      var query  =  ( typeof( arrived )  ===  "object" );
      var $multi;
      if ( query ) {
         query  =  arrived.query;
         if ( query ) {
            query  =  query.pages[ query.pageids[ 0 ] ];
            if ( query ) {
               query  =  query.imageinfo;
               if ( query ) {
                  if ( query.length === 2 ) {
                     $multi  =  jQuery( "<span />" );
                     FAdm.file.lone  =  false;
                     $multi.text( "... " + FAdm.trans.vsn.say );
                     FAdm.trans.$content.append( $multi );
                     $multi  =  jQuery( FAdm.trans.vsn.sel );
                     if ( $multi.length ) {
                        $multi.attr( "style", null );
                     }
                  }
               }
            }
         }
      }
   };   // .trans.vsn.found()



};   // .bb.trans()
mediaWiki.libs.fileAdm.bb.trans( mediaWiki.libs.fileAdm, mediaWiki );
delete mediaWiki.libs.fileAdm.bb.trans;



//-----------------------------------------------------------------------



mediaWiki.libs.fileAdm.bb.users  =  function ( FAdm, mw ) {
   // User rights management
   // 2012-08-30 PerfektesChaos@de.wikipedia
   "use strict";
   if ( typeof FAdm.users !== "object" ) {
      FAdm.users  =  { };
   }



/************************************************************************
* Zur Beschleunigung werden für Zugangsbeschränkungen Cookies benutzt.
* Die Cookies sind sitzungsbezogen;
  beim Starten des Browsers
  werden Cookies der letzten Sitzung nicht berücksichtigt.
* Der Zugang wird über einmaligen Abruf von Schnipsel-Seiten ermöglicht.
* Die Cookies merken sich positives wie negatives Ergebnis.
* Ein Admin kann Zweitaccount als Normalo haben ("Jodo" und "Jodo Test").
* Auf eigene Verantwortung kann ein session cookie
  ein Ablaufdatum erhalten; die Schnipsel-Seite wird dann ignoriert.
* Codes:
** Q = DÜP
** R = WPDK
** T = CTB
************************************************************************/



   FAdm.users.fair  =  function ( adjust ) {
      // Precondition:
      //    adjust  -- string with source text
      // Postcondition:
      //    string with source text, but user names standardized
      // Uses:
      //    >  .ns.sUsers
      //    >  .ns.sUser
      //    >< .ns.reUsers
      //    .users.fetch()
      // 2013-08-25 PerfektesChaos@de.wikipedia
      if ( ! FAdm.ns.reUsers ) {
         FAdm.ns.fetch( true );
         FAdm.ns.reUsers  =
                         new RegExp( "\\[\\[ *" + FAdm.ns.sUsers + ": *",
                                     "gi" );
      }
      return adjust.replace( FAdm.ns.reUsers,
                             "[[" + FAdm.ns.sUsers + ":" );
//   .users.fair() Benutzer|Benutzerin
   };   // .users.fair()



   FAdm.users.familiar  =  function ( ask, already, apply ) {
      // Extend a session cookie for this task and user
      // Precondition:
      //    ask      -- kind of task
      //    already  -- true: preserve current content
      //    apply    -- string to be appended, or null for deletion
      // Postcondition:
      //    Cookie was set
      // Uses:
      //    >  .users.i
      //    jQuery.cookie()
      // 2012-01-07 PerfektesChaos@de.wikipedia
      var select  =  "fileAdm" + ask;
      var stored;
      var story   =  apply;
      if ( already && apply ) {
         stored  =  jQuery.cookie( select );
         if ( typeof( stored )  !==  "string" ) {
            stored  =  "";
         }
         if ( stored.indexOf( this.i )  <  0 ) {
            story  =  stored + apply;
         }
      }
      if ( story !== apply ) {
         jQuery.cookie( select,
                        story,
                        { expires: null,
                          path:    "/" } );
      }
   };   // .users.familiar()



   FAdm.users.fetch  =  function ( advanced ) {
      // Set user properties
      // Precondition:
      //    advanced  -- true: advanced functionality (RegExp)
      // Postcondition:
      //    User properties fetched
      // Uses:
      //    >  .ns.nUser
      //    >< .users.n
      //    >< .users.w
      //    >< .ns.sUser
      //    >< .ns.sUsers
      //    .ns.fetch()
      //    mw.config.get()
      //    mw.util.wikiUrlencode()
      // 2013-08-25 PerfektesChaos@de.wikipedia
      var s;
      if ( ! this.n ) {
         this.n  =  mw.config.get( "wgUserName" );
      }
      if ( ! this.w ) {
         this.w  =  mw.util.wikiUrlencode( this.n );
      }
      if ( ! FAdm.ns.sUser ) {
         FAdm.ns.sUser  =  FAdm.ns.fetch( FAdm.ns.nUser );
      }
      if ( advanced  &&  ! FAdm.ns.sUsers ) {
         FAdm.ns.every  =  mw.config.get( "wgNamespaceIds" );
         for ( s in FAdm.ns.every ) {
            if ( FAdm.ns.every[ s ] === FAdm.ns.nUser ) {
               FAdm.ns.sUsers  =  ( FAdm.ns.sUsers
                                              ?  FAdm.ns.sUsers + "|" + s
                                              :  "(?:" );
            }
         }   // for s in .ns.every
         FAdm.ns.sUsers  =  FAdm.ns.sUsers + ")";
      }
   };   // .users.fetch()



   FAdm.users.fidelity  =  function () {
      // Check whether current user is sysop
      // Postcondition:
      //    Returns true iff sysop
      // Uses:
      //    mw.config.get()
      // 2011-08-26 PerfektesChaos@de.wikipedia
      var g  =  mw.config.get( "wgUserGroups" );
      var i;
      var n;
      var r  =  false;
      if ( typeof( g )  ===  "object" ) {
         n  =  g.length;
         for ( i = 0;  i < n;  i++ ) {
            r  =  ( g[i] === "sysop" );
            if ( r ) {
               break;   // for i
            }
         }   // for i
      }
      return r;
   };   // .users.fidelity()



   FAdm.users.flag  =  function ( ask, advanced ) {
      // Extend cookie for this task and user permission
      // Precondition:
      //    ask       -- kind of task
      //    advanced  -- true: advanced functionality
      // Uses:
      //    >  .users.i
      //    .users.familiar()
      // 2011-07-31 PerfektesChaos@de.wikipedia
      var s  =  this.i  +  ( advanced ? "*" : "-" )  +  "!";
      this.familiar( ask, true, s );
   };   // .users.flag()



   FAdm.users.flush  =  function () {
      // Clear all cookies for user permissions
      // Postcondition:
      //    Cookies are deleted
      // Uses:
      //    .users.familiar()
      // 2011-08-24 PerfektesChaos@de.wikipedia
      this.familiar( "Q", false, null );
      this.familiar( "R", false, null );
      this.familiar( "T", false, null );
   };   // .users.flush()



   FAdm.users.found  =  function ( arrived ) {
      // Postprocess user list after ajax request
      // Precondition:
      //    arrived  -- result of ajax query for permission page
      // Postcondition:
      //    Run delegated procedure
      // Uses:
      //    >  .users.w
      //    >  .ns.sUser
      //    >  window.deferred_action
      //    .users.fetch()
      //    (window.deferred_action)
      // Remark: Used as event handler -- 'this' is not FAdm.users
      // 2011-07-31 PerfektesChaos@de.wikipedia
      var located  =  false;
      var seek;
      if ( typeof( arrived )  ===  "string" ) {
         FAdm.users.fetch();
         seek     =  "[[" + FAdm.ns.sUser + ":" + FAdm.users.w + "|";
         located  =  ( arrived.indexOf( seek )  >  0 );
      } else if ( typeof( arrived )  ===  "object" ) {
      }
      if ( typeof( window.deferred_action )  ===  "function" ) {
         window.deferred_action( located, true );
      }
   };   // .users.found()



   FAdm.users.fragment  =  function () {
      // Ensure that user identifiers are set, also cookie
      // Postcondition:
      //    Cookie identifier is defined
      // Uses:
      //    >  .users.n
      //    >  .str.dbName
      //    >< .users.i
      //    .users.fetch()
      // 2011-10-09 PerfektesChaos@de.wikipedia
      var s;
      this.fetch();
      if ( ! this.i ) {
         s       =  this.n.replace( /~/g, "%7E" ).replace( /!/g, "%21" );
         this.i  =  "!" + FAdm.str.dbName + "." + s + "~";
      }
   };   // .users.fragment()



   FAdm.users.friend  =  function ( ask, access, action ) {
      // Trigger advanced procedures if user has permission
      // Precondition:
      //    ask     -- kind of task to be done
      //    access  -- curid of permission page
      //    action  -- function to be called if user has permission
      // Postcondition:
      //    Procedures are triggered directly or delegated
      // Uses:
      //    >  .users.i
      //     < window.deferred.doit
      //    .users.fragment()
      //    (.users.found)
      //    jQuery.cookie()
      //    mw.config.get()
      //    jQuery.get()
      // 2011-08-30 PerfektesChaos@de.wikipedia
      var k       =  -2;
      var query;
      var source;
      var stored  =  jQuery.cookie( "fileAdm" + ask );
      this.fragment();
      if ( typeof( stored )  ===  "string" ) {
         k  =  stored.indexOf( this.i );
      } else {
         stored  =  "";
      }
      if ( k < 0 ) {
         if ( access > 0 ) {
            query   =  { action: "raw",
                         curid:  access };
            source  =  mw.config.get( "wgScript" );
            window.deferred_action  =  action;
            jQuery.get( source, query, this.found );
         }
      } else if ( stored.charCodeAt( this.i.length )  ===  42 ) {
         action( true, false );
      }
   };   // .users.friend()



   window.fileAdm_ClearCookies  =  function() {
      // API: Alle fileAdm-Cookies für Benutzergruppen zurücksetzen
      // Nach Änderung der jeweiligen Schnipsel-Seite
      // Postcondition:
      //    Cookies are deleted.
      //    Returns void(0), as required in GUI action, if browser window
      // Uses:
      //    .users.flush()
      // 2011-10-03 PerfektesChaos@de.wikipedia
      mediaWiki.libs.fileAdm.users.flush();
      return void(0);
   };   // fileAdm_ClearCookies()



};   // .bb.users()
mediaWiki.libs.fileAdm.bb.users( mediaWiki.libs.fileAdm, mediaWiki );
delete mediaWiki.libs.fileAdm.bb.users;



//-----------------------------------------------------------------------



mediaWiki.libs.fileAdm.bb.wins  =  function ( FAdm ) {
   // Wins utilities
   // 2012-08-30 PerfektesChaos@de.wikipedia
   "use strict";
   if ( typeof FAdm.wins !== "object" ) {
      FAdm.wins  =  { };
   }



   FAdm.wins.forwardMode  =  function () {
      // Check whether particular links shall be shown in other windows
      // Precondition:
      //    Users might have defined .options.multiWin
      // Postcondition:
      //    Option is retrieved, data is stored as session cookie
      // Uses:
      //    >< .opt.multiWin
      //    >< .wins.lot
      //    .opt.fetch()
      // 2012-08-30 PerfektesChaos@de.wikipedia
      if ( FAdm.opt.multiWin ) {
         this.lot  =  FAdm.opt.fetch( FAdm.opt.multiWin, this.lot );
      }
   };   // .wins.forwardMode()



   FAdm.wins.forwardSingle  =  function () {
      // Divert links to single files into other browser tab if desired
      // Postcondition:
      //    Links to single files may be directed into another tab/window
      // Uses:
      //    >  .ns.nFile
      //    >  .wins.lot
      //    >  .wins.single
      //    >< .ns.sFile
      //    .wins.forwardMode()
      //    .ns.fetch()
      // 2012-08-30 PerfektesChaos@de.wikipedia
      var hype;
      var i;
      var select  =  "/wiki/";
      this.forwardMode();
      if ( ! FAdm.ns.sFile ) {
         FAdm.ns.sFile  =  FAdm.ns.fetch( FAdm.ns.nFile );
      }
      select  =  select + FAdm.ns.sFile + ":";
      for ( i = 0;  i < document.links.length;  i++ ) {
         hype  =  document.links[i];
         if ( hype.pathname.indexOf( select )  >=  0 ) {
            if ( this.lot ) {
               hype.target  =  this.single;
            } else {
               hype.removeAttribute( "target" );
            }
         }   // match
      }   // for i
   };   // .wins.forwardSingle()



};   // .bb.wins()
mediaWiki.libs.fileAdm.bb.wins( mediaWiki.libs.fileAdm );
delete mediaWiki.libs.fileAdm.bb.wins;



//-----------------------------------------------------------------------



mediaWiki.libs.fileAdm.bb.auto  =  function ( FAdm, mw ) {
   // Autorun and endrun
   // 2012-06-12 PerfektesChaos@de.wikipedia
   "use strict";



   FAdm.all.fire  =  function () {
      // Start entire toolbox on page loading if appropriate
      // Precondition:
      //    Interactive mode (web)
      // Postcondition:
      //    Returns void(0), as required in GUI action, if browser window
      //    Started various procedures if current page is appropriate.
      // Uses:
      //    >  .ns.nSpecial
      //    >  .ns.nProject
      //    >  .ns.nOthers1
      //    >  .ns.nFile
      //    >  .ns.nCat
      //    >  .cat.start
      //     < .ns.is
      //     < .str.action
      //     < .str.page.scp
      //     < .misc.pageid
      //     < .str.page.title
      //    .all.fit()
      //    (.guide.action)
      //    (.file.action)
      //    (.cat.action)
      //    mw.util.getParamValue()
      //    mw.config.get()
      //    jQuery().ready();
      // 2012-02-07 PerfektesChaos@de.wikipedia
      var exec    =  false,
          learnt  =  false,
          lf;
      if ( mw.util.getParamValue( "oldid" ) === null ) {
         FAdm.ns.is  =  mw.config.get( "wgNamespaceNumber" );
         switch ( FAdm.ns.is ) {
            case FAdm.ns.nSpecial :
               FAdm.str.page.scp  =
                           mw.config.get( "wgCanonicalSpecialPageName" );
               lf   =  ( FAdm.str.page.scp === "Listfiles"  ||
                         FAdm.str.page.scp === "Newimages" );
               if ( lf ) {
                  exec  =  FAdm.guide.action;
               }
               break;
            case FAdm.ns.nProject :
            case FAdm.ns.nOthers1 :
//          case FAdm.ns.nUser :
               FAdm.str.action  =  mw.config.get( "wgAction" );
               if ( FAdm.str.action === "view" ) {
                  exec  =  FAdm.guide.action;
               }
               break;
            case FAdm.ns.nFile :
               FAdm.misc.pageid  =  mw.config.get( "wgArticleId" );
               if ( FAdm.misc.pageid > 0 ) {   // not only on Commons
                  exec  =  FAdm.file.action;
               }
               break;
            case FAdm.ns.nCat :
               learnt  =  true;
               FAdm.all.fit();
               FAdm.str.page.title  =  mw.config.get( "wgTitle" );
               if ( ! FAdm.str.page.title.indexOf( FAdm.cat.start ) ) {
                  if ( FAdm.str.page.title !== FAdm.cat.start ) {
                     exec  =  FAdm.cat.action;
                  }
               }
               break;
         }   // switch wgNamespaceNumber
         if ( exec ) {
            if ( ! learnt ) {
               FAdm.all.fit();
            }
            if ( exec ) {   // might have been disabled for this project
               jQuery( document ).ready( exec );
            }
         }
      }
      return void(0);
   };   // .all.fire()



   if ( FAdm.identity === undefined ) {   // prevent multiple load
      FAdm.identity  =  FAdm.vsn;
      mw.loader.state( "w:de:WP:fileAdm", "ready" );
      jQuery( document ).trigger( "loadWikiScript",
                                  [ "fileAdm", FAdm.vsn ] );
      mw.loader.using( [ "user",
                         "mediawiki.user",
                         "mediawiki.util",
                         "jquery.cookie" ],
                       FAdm.all.fire() );   // autoRun()
   } else {
      window.alert( "fileAdm: multiple load --"
                    + " may have destroyed configuration data" );
   }



};   // .bb.auto()
mediaWiki.libs.fileAdm.bb.auto( mediaWiki.libs.fileAdm, mediaWiki );
delete mediaWiki.libs.fileAdm.bb.auto;



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



/// end of fileAdm.js

</nowiki>