Benutzer:Doc Taxon/import.js

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

Hinweis: Leere nach dem Veröffentlichen den Browser-Cache, um die Änderungen sehen zu können.

  • Firefox/Safari: Umschalttaste drücken und gleichzeitig Aktualisieren anklicken oder entweder Strg+F5 oder Strg+R (⌘+R auf dem Mac) drücken
  • Google Chrome: Umschalttaste+Strg+R (⌘+Umschalttaste+R auf dem Mac) drücken
  • Internet Explorer/Edge: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
  • Opera: Strg+F5
/// <syntaxhighlight lang="javascript"><nowiki> i m p o r t U t i l i t y
/// WP/importUtility/?.js
/// 2013-05-12 PerfektesChaos@de.wikipedia
//
// ResourceLoader:  compatible;
//    dependencies: user,
//                  mediawiki.api, mediawiki.api,
//                  mediawiki.user, mediawiki.util
//    namespaces:   -1, 4
//    doc:          w:de:Wikipedia:Importwünsche/importUtility
/// Fingerprint: #0#0#
/// @license GPL [//www.mediawiki.org/w/COPYING] (+GFDL, LGPL, CC-BY-SA)
/*jshint  curly:true, forin:false, latedef:true, laxbreak:true,
          strict:true, trailing:true, undef:true, white:false          */
/*global  window, document, jQuery, mediaWiki                          */
/*jslint  forin:false, plusplus: true, vars: true, white: true         */
/*globals window: true, document: true, jQuery: true, mediaWiki: true  */



( function ( mw, $ ) {
   "use strict";
   var IUTIL,
       vsn    =  -0.782;
   if ( typeof mw.libs.importUtility  !==  "object"   ||
        ! mw.libs.importUtility ) {
      mw.libs.importUtility  =  { };
   }
   IUTIL       =  mw.libs.importUtility;
   IUTIL.doc   =  "[[w:de:Wikipedia:Importwünsche/importUtility]]";
   IUTIL.type  =  "importUtility";
   IUTIL.vsn   =  vsn;
   if ( ! IUTIL.loaded ) {
      IUTIL.archive     =  { };
      IUTIL.batch       =  { };
      IUTIL.cnf         =  { };
      IUTIL.difflink    =  { };
      IUTIL.edit        =  { };
      IUTIL.form        =  { };
      IUTIL.greet       =  { };
      IUTIL.known       =  { };
      IUTIL.mod         =  { };
      IUTIL.notify      =  { };
      IUTIL.quiet       =  { };
      IUTIL.proj        =  { };
      IUTIL.rename      =  { };
      IUTIL.spec        =  { };
      IUTIL.table       =  { };
      IUTIL.utl         =  { };
      IUTIL.versions    =  { max:    1000,
                             sketch: "<!--#rv-->"
                           };
      IUTIL.zone        =  { };
      IUTIL.cnf.dewiki  = { archive:
                            { sectDone: "(erl.)",
                              sectHead: "h3",
                              sectTerm: "(erledigt)",
                              solvedIU: "{{Erledigt|",
                              stopIU:   "{{Nicht archivieren"
                                        + "|Zeigen=nein}}"
                            },
                            difflink:
                            { start:   "<init time=\"",
                              suggest: "Antrag"
                            },
                            edit:
                            { lazyFr: false,
                              lazyTo: false,
                              shift:    "\\* *'''Ziel''': *"
                                      + "\\[{{(?:FULLURL|fullurl):"
                                      + "([^|\n]*)"
                                      + "\\|action=history",
                              sketch:   "Versionsanzahl:",
                              source:   "\\* *'''Fremdlemma''': *"
                                      + "\\[{{(?:FULLURL|fullurl):"
                                      + "([a-z][-a-z]+):"
                                      + "([^|\n]+)"
                                      + "\\|action=history",
                              swap:   "{{Anfrage auf Upload stellen}}"
                            },
                            notify:
                            { sect:     "Dein Importwunsch zu"
                                        + " [[:{{{s}}}]]",
                              skeleton: "Wikipedia:Importwünsche/"
                                        + "Benutzernachricht"
                            },
                            quiet:
                            { source: "Wikipedia:Importwünsche/Robinson"
                            },
                            spec:
                            { "sourceTW": "WP:IMP",
                              "sourceIU": "WP:IU"
                            },
                            table:
                            { source:  "Benutzer:Importartikel",
                              support: "Importwünsche/Wartung"
                            },
                            minutes:  60,   // timeoffset
                            slang:    "de",
                            submitUP: "Importwünsche/Importupload",
                            submitTW: "Importwünsche"
                          };   // 2013-01-23
      IUTIL.cnf.swift  =  IUTIL.type + "Form";
         // sessionStorage item ID for form data
         // Uses:
         //    >  .type
         // 2012-12-15 PerfektesChaos@de.wikipedia
      IUTIL.cnf.spooling  =  "//upload.wikimedia.org/wikipedia/commons"
                             + "/d/de/Ajax-loader.gif";
         // throbber URL
         // 2012-12-15 PerfektesChaos@de.wikipedia
   }



   // Requires: JavaScript  1.3  String.fromCharCode
   //           MediaWiki   1.18 (mw.libs, jQuery core)



   IUTIL.cnf.texts  =  {
      // 2013-01-21 PerfektesChaos@de.wikipedia
      "AjaxWait":      {"en": "Contacting server",
                        "de": "Kommuniziere mit dem GROSSEN GURU"},
      "Archive":       {"en": "Resolved",
                        "de": "Erledigt"},
      "Cancel":        {"en": "Cancel",
                        "de": "Abbruch"},
      "Completed":     {"en": "Completed",
                        "de": "Abgearbeitet"},
      "Count":         {"en": "Number of revisions:",
                        "de": "Versionsanzahl:"},
      "Counting":      {"en": "Counting revisions ...",
                        "de": "Zähle Versionen ..."},
      "DeleteIssue":   {"en": "Delete",
                        "de": "Löschen"},
      "Done":          {"en": "(done)",
                        "de": "(erl.)"},
      "Error":         {"en": "ERROR!",
                        "de": "FEHLER!"},
      "ErrorAjax":     {"en": "ERROR!<br />Ajax transfer failed.",
                        "de": "FEHLER!<br />Ajax (API) fehlgeschlagen."},
      "ErrorAlready":  {"en": "ERROR!\nPage has been processed already.",
                        "de": "FEHLER!\nSeite wurde bereits angepasst\n"
                              + "{{Importartikel}} schon eingefügt."},
      "ErrorData":     {"en": "Data not recognized",
                        "de": "Daten wurden nicht erkannt"},
      "ErrorNoUserPg": {"en": "ERROR!\nNot a user subpage",
                        "de": "FEHLER!\nKeine Benutzer-Unterseite."},
      "ErrorSignat":   {"en": "ERROR!\nSignature not recognized",
                        "de": "FEHLER!\nSignatur nicht lesbar"},
      "Export":        {"en": "Export",
                        "de": "Export"},
      "GreetingAdd":   {"en": "Optional addendum for message,"
                              + " terminated by greetings."
                              + " Free pipe symbols '|' not permitted."
                              + " <strong>No Preview!</strong>",
                        "de": "Optionale Ergänzung der Nachricht,"
                              + " endend mit Grußformel."
                              + " <strong>Keine Vorschau!</strong>"},
      "Malicious":     {"en": "Malicious data detected in field",
                        "de": "Bösartige Daten gefunden im Feld"},
      "Move":          {"en": "Move imported page",
                        "de": "Importierte Seite verschieben"},
      "Moved":         {"en": "Page moved",
                        "de": "Importierte Seite verschoben"},
      "MoveSpace":     {"en": "Source not in user space",
                        "de": "Quellseite nicht im BNR"},
      "MoveToSame":    {"en": "Source and target page equal",
                        "de": "Quellseite gleich Zielseite"},
      "Moving":        {"en": "Page moving",
                        "de": "Importierte Seite wird verschoben"},
      "NotFound":      {"en": "Page not found",
                        "de": "Seite wurde nicht gefunden"},
      "NoUserName":    {"en": "No user name",
                        "de": "Kein Benutzername"},
      "PageAdapt":     {"en": "Adapt page text",
                        "de": "Seitentext anpassen"},
      "PageAdapted":   {"en": "Page has been adapted.",
                        "de": "Seite wurde angepasst."},
      "PageAdapting":  {"en": "Page adaption.",
                        "de": "Seite wird angepasst."},
      "PageUpdated":   {"en": "Page has been updated.",
                        "de": "Seite wurde aktualisiert."},
      "Robinson":      {"en": "No notification required",
                        "de": "Benötigt keine Benachrichtigung"},
      "SendNotifier":  {"en": "Send notification",
                        "de": "Sende Benachrichtigung"},
      "Start":         {"en": "Start import",
                        "de": "Import starten"},
      "Started":       {"en": "Import has been started.",
                        "de": "Import gestartet."},
      "Swap":          {"en": "Request at Upload",
                        "de": "Anfrage auf Upload"},
      "Tic":           {"en": String.fromCharCode(10003)},
      "Update":        {"en": "Update table",
                        "de": "Aktualisiere Tabelle"},
      "UserNotified":  {"en": "User has been notified.",
                        "de": "Benutzer wurde benachrichtigt."},
      "UserNotify":    {"en": "User notifícation",
                        "de": "Benutzer informieren"},
      "UserNotifying": {"en": "User notification.",
                        "de": "Benutzer wird benachrichtigt."}
   };   // .cnf.texts



   IUTIL.cnf.trans  =  {
      // 2012-11-30 PerfektesChaos@de.wikipedia
      "de" :        "de",
      "de-at" :     "de",
      "de-ch" :     "de",
      "de-formal" : "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"
   };   // .cnf.trans



   IUTIL.archive.fault  =  function ( about ) {
      // Show API failure on archive stamp
      // Precondition:
      //    about  -- JSON info of ajax query or string
      // Uses:
      //    >  .archive.$div
      //    jQuery().empty()
      //    jQuery().append()
      //    mw.log()
      // Remark: Used as event handler -- 'this' is not IUTIL.archive
      // 2012-12-26 PerfektesChaos@de.wikipedia
      var $d  =  IUTIL.archive.$div;
      $d.empty();
      $d.append( $( "<span style='border: solid 2px #FF0000;"
                              + " color: #FF0000;"
                              + " margin-left: 5px;'>"
                    + "<strong>ERROR</strong>"
                    + ( typeof about  ===  "string"   ?   " " + about
                                                      :   "" )
                    + "</span>" ) );
      mw.log( {loud:true}, "IUTIL.archive.fault()", 2, about );
   };   // .archive.fault()



   IUTIL.archive.feed  =  function ( arrived ) {
      // Set archive marker by API
      // Precondition:
      //    arrived  -- JSON result of ajax query
      // Uses:
      //    >  mw.Api
      //    >  .type
      //    >  .vsn
      //    mw.user.tokens.get()
      //    .cnf.feature()
      //    .archive.flip()
      //    mw.Api.post()
      //    .archive.fault()
      //    (.archive.fine)
      //    (.archive.fault)
      // Remark: Used as event handler -- 'this' is not IUTIL.archive
      // 2013-01-28 PerfektesChaos@de.wikipedia
      var i       =  false,
          n       =  false,
          q,
          shift   =  false,
          stamp,
          story,
          sucks   =  "feed",
          sum     =  false,
          swap    =  false,
          w;
      if ( arrived ) {
         q  =  arrived.query;
         if ( q ) {
            w  =  q.normalized;
            if ( w ) {
               w  =  w[ 0 ];
               if ( w ) {
                  shift  =  w.to;
                  w      =  /#([1-9][0-9]*)$/.exec( w.from );
                  if ( w ) {
                     n  =  parseInt( w[ 1 ],  10 );
                  }
               }
            }
            w  =  q.pageids;
            if ( w ) {
               i  =  w[ 0 ];
            }
            if ( i ) {
               w  =  q.pages;
               if ( w ) {
                  w  =  w[ i ];
                  if ( w ) {
                     w  =  w.revisions;
                     if ( w ) {
                        w  =  w[ 0 ];
                        if ( w ) {
                           stamp  =  w.timestamp;
                           story  =  w[ "*" ];
                           if ( story ) {
                              w  =  IUTIL.archive.flip( story );
                              if ( w ) {
                                 if ( w[ 0 ] === story ) {
                                    swap   =  false;
                                    sucks  =  sucks + "/equal";
                                 } else {
                                    swap  =  w[ 0 ];
                                    sum   =  "/* " + w[ 1 ] + " */ ";
                                 }
                              }
                           }
                        }
                     }
                  }
               }
            }
         }
      }
      if ( n && shift && sum && swap && stamp ) {
         q  =  new mw.Api();
         w  =  { action:        "edit",
                 token:         mw.user.tokens.get( "csrfToken" ),
                 basetimestamp: stamp,
                 minor:         false,
                 section:       n,
                 summary:       sum
                                + IUTIL.cnf.feature( "Archive", true )
                                + " / " + IUTIL.type + " " + IUTIL.vsn,
                 text:          swap,
                 title:         shift };
         q.post( w ).done( IUTIL.archive.fine )
                    .fail( IUTIL.archive.fault );
      } else {
         IUTIL.archive.fault( sucks );
      }
   };   // .archive.feed()



   IUTIL.archive.fine  =  function () {
      // Show API success on archive stamp
      // Uses:
      //    >  .archive.$div
      //    jQuery().empty()
      //    jQuery().append()
      //    .cnf.feature()
      // Remark: Used as event handler -- 'this' is not IUTIL.archive
      // 2012-12-26 PerfektesChaos@de.wikipedia
      var $d  =  IUTIL.archive.$div;
      $d.empty();
      $d.append( $( "<span style='border: solid 1px #00A000; "
                              + " color: #00A000;"
                              + " padding: 2px;"
                              + " margin-left: 5px;'>"
                    + IUTIL.cnf.feature( "Archive", false )
                    + "</span>" )  );
   };   // .archive.fine()



   IUTIL.archive.fire  =  function ( address ) {
      // Set archive marker by API: Retrieve section content
      // Precondition:
      //    address  -- section number
      // Uses:
      //    >  mw.Api
      //    >  .cnf.project.submitUP
      //    >  mw.util.$content
      //     < .archive.$div
      //    jQuery().find()
      //    mw.Api.get()
      //    jQuery().empty()
      //    .batch.$flow()
      //    jQuery().append()
      //    (.archive.feed)
      //    (.archive.fault)
      // Remark: Used as event handler -- 'this' is not IUTIL.archive
      // 2012-12-31 PerfektesChaos@de.wikipedia
      var q   =  new mw.Api(),
          w   =  { action:       "query",
                   indexpageids: true,
                   prop:         "revisions",
                   rvlimit:      1,
                   rvprop:       "content|timestamp",
                   titles:       "Project:" + IUTIL.cnf.project.submitUP
                                            + "#" + address,
                   rvsection:    address },
          $d  =  mw.util.$content.find( "#importUtility_" + address );
      if ( $d.length ) {
         q.get( w ).done( IUTIL.archive.feed )
                   .fail( IUTIL.archive.fault );
         IUTIL.archive.$div  = $d;
         $d.empty();
         $d.append( IUTIL.batch.$flow( 16, "margin-left:10px" ) );
      }
   };   // .archive.fire()



   IUTIL.archive.flip  =  function ( already ) {
      // Modify text in order to set archive template
      // Precondition:
      //    already  -- text
      // Postcondition:
      //    Return Array, or false if nothing to do
      //           [0]  modified text
      //           [1]  basic section title
      // Uses:
      //    this
      //    >  .cnf.project.archive.sectDone
      //    >  .cnf.project.archive.sectTerm
      //    >  .cnf.project.archive.stopIU
      //    >  .cnf.project.archive.solvedIU
      // 2013-01-28 PerfektesChaos@de.wikipedia
      var g,
          pA    =  IUTIL.cnf.project.archive,
          slot  =  already,
          s     =  " " + pA.sectDone + " ==",
          sT    =  " " + pA.sectTerm + " ",
          sum   =  false,
          i     =  slot.indexOf( s );
      if ( i > 0 ) {
         sum   =  slot.substr( 0, i );
         slot  =  sum  +  sT  +  "=="  +  slot.substr( i + s.length );
      } else if ( slot.indexOf( sT )  <  0 ) {
         g  =  /\b((=+)([^=\n].*[^=\n]))\2\n/.exec( slot );
         if ( g ) {
            if ( g[ 1 ].length > 6 ) {
               sum   =  g[ 1 ];
               slot  =  sum  +  sT  +  g[ 2 ]  +  "\n"
                        +  slot.substr( g[ 0 ].length );
            }
         }
      }
      s  =  pA.stopIU;
      i  =  slot.indexOf( s );
      if ( i > 0 ) {
         slot  =  slot.substr( 0, i )  +  slot.substr( i + s.length );
      }
      i  =  slot.toLowerCase().indexOf( pA.solvedIU.toLowerCase() );
      if ( i < 0 ) {
         slot  =  slot + "\n\n" + pA.solvedIU + "1=~~~~}}";
      }
      if ( sum ) {
         g  =  new RegExp( "^==+ *([^ ].*[^ ]) *$" );
         g  =  g.exec( sum );
         if ( g ) {
            sum  =  g[ 1 ];
         }
      }
      return  ( slot === already  ?  false
                                  :  [ slot, sum ] );
   };   // .archive.flip()



   IUTIL.archive.found  =  function ( access ) {
      // Equip IU section with archive button, if appropriate
      // Precondition:
      //    access  -- index (not used)
      // Postcondition:
      //    Return true for continued iteration
      // Uses:
      //    >  .cnf.project.archive.sectDone
      //    .cnf.feature()
      //    jQuery()
      //    jQuery().text()
      //    jQuery().append()
      // Remark: Used as jQuery callback -- 'this' is DOM element
      // 2013-05-12 PerfektesChaos@de.wikipedia
      var $h  =  $( this ),
          g,
          pA  =  IUTIL.cnf.project.archive,
          s   =  $h.children( "span.mw-headline" ).text();
      if ( s.indexOf( pA.sectDone )  >  0 ) {
         s  =  $h.children( "span.mw-editsection" )
                 .children( "a" ).attr( "href" );
         if ( s ) {
            g  =  /section=([1-9][0-9]*)\b/.exec( s );
            if ( g ) {
               g  =  g[1];
               s  =   "<span id='importUtility_" + g + "'>"
                      + " &nbsp; "
                      + "<button type='button'"
                             + " onclick='mw.libs.importUtility"
                                            + ".archive.fire(" + g + ")'"
                       + ">"
                      + IUTIL.cnf.feature( "Archive", false )
                      + "</button>"
                    + "</span>";
               $h.append( $( s ) );
            }
         }
      }
      return true;
   };   // .archive.found()



   IUTIL.archive.furnish  =  function (  ) {
      // Equip IU page with appropriate archive buttons
      // Uses:
      //    this
      //    >  mw.util.$content
      //    >  .cnf.project.archive.sectHead
      //    jQuery().find()
      //    jQuery().each()
      //    (.archive.found)
      // 2012-12-26 PerfektesChaos@de.wikipedia
      mw.util.$content.find( IUTIL.cnf.project.archive.sectHead )
                      .each( this.found );
   };   // .archive.furnish()



   IUTIL.batch.failed  =  function ( apply ) {
      // Equip page with error message box
      // Precondition:
      //    apply   -- String: HTML error message text, or false
      // Uses:
      //    >  .$msg
      //    jQuery().empty()
      //    jQuery().attr()
      //    .cnf.feature()
      //    jQuery().append()
      // 2012-12-31 PerfektesChaos@de.wikipedia
      IUTIL.$msg.empty();
      IUTIL.$msg.attr( "style",     "border: solid 2px #FF0000;"
                                 + " color: #FF0000;"
                                 + " margin: 3px;"
                                 + " padding: 1em;" );
      IUTIL.$msg.append(  $( ( apply  ?  apply
                               :  "<strong>"
                                  +  IUTIL.cnf.feature( "Error", false )
                                  +  "</strong>" ) ) );
   };   // .batch.failed()



   IUTIL.batch.fine  =  function ( apply ) {
      // Equip page with success message
      //    apply  -- message keyword
      // Uses:
      //    this
      //    >  .$msg
      //    jQuery().empty()
      //    jQuery().attr()
      //    jQuery().text()
      //    jQuery().append()
      //    .cnf.feature()
      // 2012-12-31 PerfektesChaos@de.wikipedia
      var $t  =  $( "<span />" );
      IUTIL.$msg.empty();
      IUTIL.$msg.attr( "style",     "border: solid 1px #00A000;"
                                 + " color: #00A000;"
                                 + " margin: 3px;"
                                 + " padding: 1em;" );
      $t.text( IUTIL.cnf.feature( apply, false ) );
      IUTIL.$msg.append( $t );
   };   // .batch.fine()



   IUTIL.batch.fired  =  function ( await ) {
      // Equip page with waiting loop and throbber
      //    await   -- message keyword, or false
      // Uses:
      //    this
      //    >  .$msg
      //    jQuery().empty()
      //    jQuery().attr()
      //    .batch.$flow()
      //    jQuery().append()
      //    jQuery().text()
      //    .cnf.feature()
      // 2013-01-08 PerfektesChaos@de.wikipedia
      var $t  =  $( "<span />" );
      IUTIL.$msg.empty();
      IUTIL.$msg.attr( "style",     "border: solid 1px #0000FF;"
                                 + " color: #0000FF;"
                                 + " margin: 3px;"
                                 + " padding: 1em;" );
      IUTIL.$msg.append( this.$flow() );
      IUTIL.$msg.append( $( "<span>&nbsp; &nbsp;</span>" ) );
      $t.text( IUTIL.cnf.feature( ( await ? await : "AjaxWait" ),
                                  false ) );
      IUTIL.$msg.append( $t );
   };   // .batch.fired()



   IUTIL.batch.$flow  =  function ( alter, adapt ) {
      // Create throbber
      // Precondition:
      //    alter  -- number of pixels other than standard, or false
      //    adapt  -- additional style, or false
      // Postcondition:
      //    Return jQuery with throbber IMG
      // Uses:
      //    >  .cnf.spooling
      //    jQuery()
      // 2012-12-31 PerfektesChaos@de.wikipedia
      var s  =  "<img src='" + IUTIL.cnf.spooling + "'"
                + " height='"  +  ( alter ? alter : "24" )  + "'"
                + ( adapt  ?  " style='" + adapt + "'"  :  "" )
                + " />";
      return  $( s );
   };   // .batch.$flow()



   IUTIL.cnf.favorite  =  function () {
      // Guess user language
      // Uses:
      //    this
      //    >  .cnf.trans
      //    >< .cnf.slang
      //    mw.config.get()
      // 2012-12-23 PerfektesChaos@de.wikipedia
      var s;
      if ( ! this.slang ) {
         s           =  mw.config.get( "wgUserLanguage" ).toLowerCase();
         s           =  this.trans[ s ];
         this.slang  =  ( s ? s : "en" );
      }
   };   // .cnf.favorite()



   IUTIL.cnf.feature  =  function ( apply, adhere ) {
      // Wrap message text access for user or project language
      // Precondition:
      //    apply   -- text keyword
      //    adhere  -- true: project language;  else user language
      // Postcondition:
      //    Return text closest to user language
      // Uses:
      //    this
      //    >  .cnf.slang
      //    >  .cnf.texts
      //    >  .cnf.project.slang
      //    .cnf.favorite()
      // Remark: To be replaced
      //         if one day ResourceLoader3 gives access to
      //         gadget@translatewiki
      // 2012-12-18 PerfektesChaos@de.wikipedia
      var e,
          r, slang;
      if ( ! this.slang ) {
         this.favorite();
      }
      e  =  this.texts[ apply ];
      if ( e ) {
         slang  =  ( adhere ? this.project.slang : this.slang );
         r  =  e[ slang ];
         if ( ! r ) {
            r  =  e.en;
            if ( ! r ) {
               r  =  "???" + apply + "???";
            }
         }
      } else {
         r  =  "***" + apply + "***";
      }
      return r;
   };   // .cnf.feature()



   IUTIL.difflink.fault  =  function ( arrived ) {
      // Show API failure on difflink generation
      // Precondition:
      //    arrived  -- JSON info of ajax query
      // Uses:
      //    .batch.failed()
      //    mw.log()
      // Remark: Used as event handler -- 'this' is not IUTIL.difflink
      // 2013-01-05 PerfektesChaos@de.wikipedia
      IUTIL.batch.failed( false );
      mw.log( {loud:true}, "IUTIL.difflink.fault()", 2, arrived );
   };   // .difflink.fault()



   IUTIL.difflink.fire  =  function ( applicant ) {
      // Turn REVISIONTIMESTAMP of request into difflink
      // Precondition:
      //    applicant  -- originator nick, or false
      // Uses:
      //    this
      //    >  .cnf.project.difflink.start
      //    >  mw.Api
      //     < .idPage
      //    .edit.feed()
      //    .zone.factory()
      //    .utl.format()
      //    mw.config.get()
      //    mw.Api.get()
      //    (.difflink.found)
      //    (.difflink.fault)
      // 2013-01-23 PerfektesChaos@de.wikipedia
      var b, e, i, s, w,
          d  =  false,
          q  =  IUTIL.cnf.project.difflink.start;
      if ( q ) {
         s  =  IUTIL.edit.feed( false );
         if ( s ) {
            i  =  s.indexOf( q );
            if ( i > 0 ) {
               s  =  s.substr( i + q.length,  14 );
               if ( /^[0-9]{14}$/.test( s ) ) {
                  d  =  IUTIL.zone.factory( s );
               }
            }
         }
      }
      if ( d ) {
         IUTIL.idPage  =  mw.config.get( "wgArticleId" );
         i  =  d.valueOf();
         d  =  15000;
         b  =  new Date( i + d );
         e  =  new Date( i - d );
         q  =  new mw.Api();
         w  =  { action:   "query",
                 prop:     "revisions",
                 rvlimit:  3,
                 rvprop:   "ids",
                 rvuser:   applicant,
                 rvstart:  IUTIL.utl.format( b ),
                 rvend:    IUTIL.utl.format( e ),
                 pageids:  IUTIL.idPage };
         q.get( w ).done( this.found ).fail( this.fault );
      }
   };   // .difflink.fire()



   IUTIL.difflink.found  =  function ( arrived ) {
      // Show API success on difflink generation
      // Precondition:
      //    arrived  -- JSON result of ajax query
      // Uses:
      //    >  .idPage
      //    >  .cnf.project.difflink.suggest
      //    >  .cnf.project.difflink.start
      //    .edit.feed()
      // Remark: Used as event handler -- 'this' is not IUTIL.difflink
      // 2013-01-21 PerfektesChaos@de.wikipedia
      var i, k,
          q  =  arrived.query,
          s;
      if ( q ) {
         q  =  arrived.query;
         if ( q ) {
            q  =  q.pages;
            if ( q ) {
               q  =  q[ IUTIL.idPage ];
               if ( q ) {
                  q  =  q.revisions;
                  if ( q ) {
                     q  =  q[ 0 ];
                     if ( q ) {
                        q  =  q.revid;
                     }
                  }
               }
               if ( q ) {
                  s  =  IUTIL.edit.feed( false );
                  if ( s ) {
                     k  =  IUTIL.cnf.project.difflink.start;
                     i  =  s.indexOf( k );
                     if ( i > 0 ) {
                        s  =  s.substr( 0, i )  +  "</span>"
                              + "([{{fullurl:{{PAGENAME}}|diff="
                              + q + "}} "
                              + IUTIL.cnf.project.difflink.suggest + "])"
                              + s.substr( i + k.length + 25 );
                        IUTIL.edit.feed( s );
                     }
                  }
               }
            }
         }
      }
   };   // .difflink.found()



   IUTIL.edit.failing  =  function ( about ) {
      // Warn on missing data
      // Precondition:
      //    about  -- explanation, or false
      // Uses:
      //    this
      //    >  .$msg
      //    jQuery().empty()
      //    .batch.failed()
      //    .cnf.feature()
      // 2012-12-31 PerfektesChaos@de.wikipedia
      IUTIL.$msg.empty();
      IUTIL.batch.failed( "<strong>"
                          + IUTIL.cnf.feature( "Error" )
                          + " &nbsp; * &nbsp; "
                          + IUTIL.cnf.feature( "ErrorData" )
                          + ( about  ?  " (" + about + ")"  :  "" )
                          + "</strong>" );
   };   // .edit.failing()



   IUTIL.edit.fault  =  function ( about ) {
      // Bounce invalid request
      // Uses:
      //    this
      //    >< .cnf.project.edit.swap
      //    .edit.feed()
      //    .edit.flag()
      //    mw.log()
      // 2012-12-19 PerfektesChaos@de.wikipedia
      this.feed( this.feed( false )
                 +  "\n\n"
                 +  IUTIL.cnf.project.edit.swap  +  " --~~~~" );
      this.flag( "Swap" );
      mw.log( {loud:true}, "IUTIL.edit.fault()", 2, about );
   };   // .edit.fault()



   IUTIL.edit.feed  =  function ( apply ) {
      // Retrieve content of text area
      // Precondition:
      //    apply  -- false: retrieve content;  string: insert
      //    document.ready
      // Postcondition:
      //    Return textarea string; or false
      // Uses:
      //    this
      //    >  .edit.$textarea
      //    >  wikEd
      //    jQuery().val()
      //    wikEd.UpdateFrame()
      //    wikEd.UpdateTextarea()
      // 2013-01-05 PerfektesChaos@de.wikipedia
      var i, j, l,
          r  =  false;
      if ( this.$textarea ) {   // editing
         l  =  ( typeof apply  ===  "string" );
         if ( l ) {
            r  =  apply;
            i  =  r.indexOf( "<!-- *** " );
            if ( i > 0 ) {
               j  =  r.indexOf( " *** -->",  i );
               if ( j > 0 ) {
                  r  =  r.substr( 0, i )  +  r.substr( j + 8 );
               }
            }
            this.$textarea.val( r );
         }
         if ( window.wikEd
              &&  typeof window.wikEd  ===  "object"
              &&  ! window.wikEd.disabled
              &&  window.wikEd.turnedOn
              &&  window.wikEd.useWikEd
              &&  window.wikEd.UpdateFrame
              &&  window.wikEd.UpdateTextarea ) {
            if ( l ) {
               window.wikEd.UpdateFrame();
            } else {
               window.wikEd.UpdateTextarea();
            }
         }
         if ( apply === false ) {
            r  =  this.$textarea.val();
         }
      }   // editing
      return r;
   };   // .edit.feed()



   IUTIL.edit.fetch  =  function () {
      // Retrieve transfer information from edit area
      // Postcondition:
      //    Returns object with appropriate data, or false
      //       .lang        -- source language other than current
      //       .from        -- source page
      //       .target      -- target page
      //       .originator  -- user
      //       .requestID   -- oldid, for upload mode
      //       .versions    -- non-empty: found
      // Uses:
      //    this
      //    >  .cnf.project
      //    >  .mode
      //    >  .cnf.project.edit.shift
      //    >  .cnf.project.edit.lazyTo
      //    >  .cnf.project.edit.source
      //    >  .versions.sketch
      //    >  .cnf.project.edit.lazyFr
      //    >< .cnf.project.edit.reFrom
      //    >< .cnf.project.edit.reTo
      //    .edit.feed()
      //    mw.config.get()
      //    .edit.failing()
      //    .edit.filter()
      // 2013-01-28 PerfektesChaos@de.wikipedia
      var g, o, p,
          r  =  false,
          s  =  this.feed( false );
      if ( s ) {
         p  =  IUTIL.cnf.project.edit;
         if ( ! p.reFrom ) {
            p.reFrom  =  new RegExp( p.source );
         }
         g  =  p.reFrom.exec( s );
         if ( ! g  &&  IUTIL.mode === 1 ) { // OBSOLET check mit DerHexer
            p.reFrom  =  new RegExp(   "\\* *"
                                     + "'''Fremdlemma''': \\[//"
                                     + "([a-z][-a-z]+)"
                                     + "\\.wiki.+\\.org"
                                     + "/w/index\\.php"
                                     + "\\?title="
                                     + "([^ \n]+)"
                                     + "&action=history " );
            g         =  p.reFrom.exec( s );
            p.reFrom  =  false;
         }
         if ( g ) {
            r  =  { "from":  g[ 2 ] };
            if ( ! p.lazyFr ) {
               r.from  =  decodeURIComponent( r.from );
               r.from  =  r.from.replace( /\+/g, " " );
            }
            if ( g[ 1 ] ) {
               if ( g[ 1 ]  !==  mw.config.get( "wgContentLanguage" ) ) {
                  r.lang  =  g[ 1 ];
               }
            }
         }
         if ( r ) {
            if ( s.indexOf( IUTIL.versions.sketch )  >  0 ) {
               r.versions  =  "*";
            }
            if ( ! p.reTo ) {
               p.reTo  =  new RegExp( p.shift );
            }
            g  =  p.reTo.exec( s );
            if ( ! g  &&  IUTIL.mode===1 ) {// OBSOLET check mit DerHexer
               p.reTo  =  new RegExp(   "\\* '''Ziel''': \\[//[-a-z]+"
                                      + "\\.wiki.+\\.org/w/index\\.php"
                                      + "\\?title="
                                      + "([^ \n]*)"
                                      + "&action=history " );
               g       =  p.reTo.exec( s );
               p.reTo  =  false;
            }
            if ( g ) {
               r.target  =  g[ 1 ];
               if ( ! p.lazyTo ) {
                  r.target  =  decodeURIComponent( r.target );
                  r.target  =  r.target.replace( /\+/g, " " );
               }
            }
            o  =  s.indexOf( "<span style=\"display:none\"" );
            if ( o >= 0 ) {
               s  =  s.substr( o + 25 );
               if ( IUTIL.mode === 2 ) {
                  g  =  "{{fullurl:{{PAGENAME}}|diff=";
                  p  =  s.indexOf( g );
                  if ( p > 0 ) {
                     p  =  s.substr( p + g.length );
                     g  =  /^([0-9]+)\}\}/.exec( p );
                     if ( g ) {
                        r.requestID  =  g[ 1 ];
                     }
                  }
               }
               o  =  s.indexOf( "\n" );
               if ( o > 0 ) {
                  s  =  s.substr( 0, o );
               }
               o  =  s.indexOf( "</span>" );
               if ( o > 0 ) {
                  s  =  s.substr( 0,  o + 1 );
               }
               g  =  />([^<\n]+)</.exec( s );
               if ( g ) {
                  r.originator  =  g[ 1 ];
               }
            }
            if ( ! r.target ) {
               r.target  =  r.from;
               if ( r.lang ) {
                  if ( ! IUTIL.cnf.space ) {
                     IUTIL.cnf.space  =
                           mw.config.get( "wgFormattedNamespaces" )[ 2 ];
                  }
                  if ( r.originator ) {
                     r.target  =  IUTIL.cnf.space + ":"
                                  + r.originator + "/"
                                  + r.target;
                  } else {
                     this.failing( IUTIL.cnf.space );
                  }
               }
            }
            r  =  this.filter( r );
         } else {
            this.failing( false );
         }
      }
      return r;
   };   // .edit.fetch()



   IUTIL.edit.fiat  =  function () {
      // Mark section as done
      // Uses:
      //    this
      //    .cnf.feature()
      //    .edit.feed()
      //    .edit.fill()
      // 2012-12-18 PerfektesChaos@de.wikipedia
      var got,
          signal  =  IUTIL.cnf.feature( "Done", true ),
          story   =  this.feed( false ),
          s,
          i       =  story.indexOf( "\n" ),
          re;
      if ( i > 6 ) {
         s  =  story.substr( 0, i );
         if ( s.substr( 0, 2 )  ===  "==" ) {
            if ( s.indexOf( signal )  <  0 ) {
               re   =  new RegExp( "^(=+[^=].*[^= ]) *(=+) *$", "" );
               got  =  re.exec( s );
               if ( got ) {
                  story  =  got[1] + " " + signal + " " + got[2]
                            +  story.substr( i );
                  this.feed( story );
               }
            }
         }
      }
      this.fill( "Done" );
   };   // .edit.fiat()



   IUTIL.edit.field  =  function () {
      // Ensure availability of edit area object
      // Uses:
      //    this
      //    >  mw.util.$content
      //    >< .edit.$textarea
      //    jQuery().find()
      //    jQuery().attr()
      // 2012-12-16 PerfektesChaos@de.wikipedia
      var $form;
      if ( ! this.$textarea ) {
         $form  =  mw.util.$content.find( "#editform" );
         if ( $form.length ) {
            this.$textarea  =  $form.find( "#wpTextbox1" );
            if ( this.$textarea.length ) {
               if ( this.$textarea.attr( "readonly" ) ) {
                  this.$textarea  =  false;
               }
            } else {
               this.$textarea  =  false;
            }
         }
      }
   };   // .edit.field()



   IUTIL.edit.file  =  function () {
      // Export page: Open form
      // Uses:
      //    mw.util.getUrl()
      //    window.open()
      // 2012-12-26 PerfektesChaos@de.wikipedia
      window.open( mw.util.getUrl( "Special:Export" ),
                   "_blank" );
alert(".file()\n Noch nicht so weit.");
   };   // .edit.file()



   IUTIL.edit.fill  =  function ( action ) {
      // Add process note on edit area and summary
      // Precondition:
      //    action  -- keyword
      // Uses:
      //    this
      //    .edit.feed()
      //    .cnf.feature()
      //    .utl.firm()
      //    .edit.flag()
      // 2012-12-15 PerfektesChaos@de.wikipedia
       var s  =  this.feed( false )
                 + "\n* "
                 + IUTIL.cnf.feature( action, true )
                 + " --"
                 + IUTIL.utl.firm();
       this.feed( s );
       this.flag( action );
   };   // .edit.fill()



   IUTIL.edit.filter  =  function ( ask ) {
      // Sanitize retrieved content
      // Precondition:
      //    ask    -- input object
      // Postcondition:
      //    Returns same or sanitized ask
      //             < .§
      // Uses:
      //    .batch.failed()
      //    .cnf.feature()
      //    window.alert()
      // 2013-01-03 PerfektesChaos@de.wikipedia
      var r  =  ask,
          stuff, symbol;
      if ( ask ) {
         for ( symbol in r ) {
            stuff  =  r[ symbol ];
            if ( stuff.indexOf( "<" )  >=  0 ) {
               r[ symbol ]  =  stuff.replace( /</g, "&lt;" );
               r[ "§" ]     =  symbol;
               stuff        =  IUTIL.cnf.feature( "Malicious" )
                               + " '" + symbol + "'";
               window.alert( stuff );
               IUTIL.batch.failed( "<strong>"
                                   + stuff + "<br /><br />"
                                   + r[ symbol ]
                                   + "</strong>" );
            }
         }   // for symbol in r
      }
      return r;
   };   // .edit.filter()



   IUTIL.edit.finish  =  function () {
      // Remove edit section content
      // Uses:
      //    this
      //    .edit.feed()
      //    .edit.flag()
      // 2012-12-15 PerfektesChaos@de.wikipedia
      this.feed( "" );
      this.flag( "Completed" );
   };   // .edit.finish()



   IUTIL.edit.finished  =  function () {
      // Mark section as resolved for archiving
      // Uses:
      //    this
      //    .archive.flip()
      //    .edit.feed()
      //    .edit.flag()
      // 2012-12-25 PerfektesChaos@de.wikipedia
      var story  =  this.feed( false );
      story  =  IUTIL.archive.flip( story );
      if ( story ) {
         this.feed( story );
         this.flag( "Archive" );
      }
   };   // .edit.finished()



   IUTIL.edit.fire  =  function ( action ) {
      // Perform action on page section editing
      // Precondition:
      //    action  -- keyword
      //               omitted: Start page processing
      // Uses:
      //    this
      //    >  .edit.$textarea
      //    .edit.field()
      //    .edit.finished()
      //    .greet.failed()
      //    .edit.finish()
      //    .edit.fiat()
      //    .edit.file()
      //    .rename.fire()
      //    .edit.fix()
      //    .edit.fill()
      //    .greet.fire()      //    .notify.fire()
      //    .edit.forward()
      //    .edit.fault()
      //    .greet.furnish()
      //    .edit.furnish()
      // 2013-01-16 PerfektesChaos@de.wikipedia
      this.field();
      if ( this.$textarea ) {
         switch ( action ) {
            case "Archive" :
               this.finished();
               break;
            case "Cancel" :
               IUTIL.greet.failed();
               break;
            case "DeleteIssue" :
               this.finish();
               break;
            case "Done" :
               this.fiat();
               break;
            case "Export" :
               this.file();
               break;
            case "Move" :
               IUTIL.rename.fire();
               break;
            case "PageAdapt" :
               this.fix();
               break;
            case "Moved" :
            case "PageAdapted" :
            case "Started" :
            case "UserNotified" :
               this.fill( action );
               break;
            case "SendNotifier" :
               IUTIL.greet.fire();
               break;
            case "Start" :
               this.forward();
               break;
            case "Swap" :
               this.fault();
               break;
           case "UserNotify" :
               IUTIL.greet.furnish();
               break;
            default:
               this.furnish();
               break;
         }   // switch action
      }
   };   // .edit.fire()



   IUTIL.edit.fix  =  function () {
      // Adapt target page content
      // Uses:
      //    this
      //    >  .type
      //     < .mod.lang
      //    .edit.fetch()
      //    .utl.fold()
      //    .mod.fire()
      //    .edit.fill()
      //    .cnf.feature()
      // 2012-12-16 PerfektesChaos@de.wikipedia
      var o  =  this.fetch(),
          t  =  IUTIL.utl.fold( o.target );
      if ( t[1] === 2 ) {
         IUTIL.mod.lang  =  o.lang;
if (wgUserName==="PerfektesChaos") {
         IUTIL.mod.fire( t );        // LIFE TEST
}
         this.fill( "PageAdapting" );
      } else {
         window.alert( IUTIL.type + "\n\n"
                       +  IUTIL.cnf.feature( "ErrorNoUserPg", false ) );
      }
alert(".fix()\n Noch nicht so weit.");
   };   // .edit.fix()



   IUTIL.edit.flag  =  function ( action ) {
      // Update summary
      // Precondition:
      //    action  -- keyword
      // Uses:
      //    this
      //    >  mw.util.$content
      //    >< .edit.$summary
      //    jQuery().find()
      //    jQuery().val()
      //    .cnf.feature()
      // 2012-12-15 PerfektesChaos@de.wikipedia
      var i, s;
      if ( ! this.$summary ) {
         this.$summary  =  mw.util.$content.find( "#wpSummary" );
      }
      s  =  this.$summary.val();
      i  =  s.indexOf( " */" );
      if ( i > 0 ) {
         s  =  s.substr( 0,  i + 3 )   +   " ";
      } else {
         s  =  s + " * ";
      }
      s  =  s  +  IUTIL.cnf.feature( action, true );
      this.$summary.val( s );
   };   // .edit.flag()



   IUTIL.edit.force  =  function ( action, assign, $append ) {
      // Insert button into suite
      // Precondition:
      //    action   -- keyword
      //    assign   -- label key, if not action
      //    $append  -- container, or false
      // Uses:
      //    this
      //    >  .edit.$buttons
      //    .cnf.feature()
      //    jQuery()
      //    jQuery().append()
      // 2013-01-16 PerfektesChaos@de.wikipedia
      var s   =  "<button type='button'"
                      + " id='importUtility_act_" + action + "'"
                      + " onclick='mw.libs.importUtility.edit.fire"
                                                + "(\"" + action + "\")'"
                      + ">"
                 +  IUTIL.cnf.feature( (  assign ? assign : action ) )
                 +  "</button>"
                 +  "<span>&nbsp;</span>",
          $c  =  ( $append ? $append : this.$buttons );
      $c.append( $( s ) );
   };   // .edit.force()



   IUTIL.edit.forward  =  function () {
      // Start special page run
      // Uses:
      //    this
      //    window
      //    >  .mode
      //    >  .cnf.project.spec.sourceTW
      //    >  .cnf.project.spec.sourceIU
      //    >  .cnf.swift
      //    >  window.sessionStorage
      //    .edit.fetch()
      //    .utl.fold()
      //    jQuery.toJSON()
      //    mw.util.getUrl()
      //    window.open()
      //    .edit.fill()
      // 2013-02-02 PerfektesChaos@de.wikipedia
      var o  =  this.fetch(),
          i, p, s, t;
      if ( o ) {
         p  =  IUTIL.cnf.project.spec;
         if ( IUTIL.mode === 1 ) {
            p  =  { "interwiki":            o.lang,
                    "frompage":             o.from,
                    "mw-interwiki-comment": p.sourceTW
                  };
            t  =  IUTIL.utl.fold( o.target );
            switch ( t[ 0 ] ) {
               case 0 :   // (main)
                  p.namespace                             =  0;
                  p[ "mw-interwiki-rootpage-interwiki" ]  =  t[ 1 ];
                  break;
               case 2 :   // user:
                  // user
                  s  =  o.target + "\f";
                  i  =  s.indexOf( "/" + o.from + "\f" );
                  if ( i < 0 ) {
                     s  =  o.target;
                  } else {
                     s  =  s.substr( 0,  i + 1 );
                  }
                  // Workaround for Special:Import target page limitation
                  i  =  s.indexOf( "/" );
                  if ( i > 0 ) {
                     s  =  s.substr( 0,  i + 1 );
                  }
                  p[ "mw-interwiki-rootpage-interwiki" ]  =  s;
                  p.originator  =  o.originator;
                  break;
            }   // switch t[ 0 ]
         } else {
            s  =  p.sourceIU   // TODO test
                  +  ( o.requestID  ?  " * " + wgServer + wgScript
                                       + "?diff=" + o.requestID
                                    :  "" )
                  + " * [["
                        +  ( o.lang  ?  o.lang + ":"  :  "" )
                        +  o.from + "]]";
            p  =  { "mw-interwiki-rootpage-upload": o.target,
                    "mw-import-comment":            s
                  };
         }
         if ( window.sessionStorage ) {
            window.sessionStorage.setItem( IUTIL.cnf.swift,
                                           $.toJSON( p ) );
         }
         window.open( mw.util.getUrl( "Special:Import" ),
                      "_blank" );
         this.fill( "Start" );
      }
   };   // .edit.forward()



   IUTIL.edit.furnish  =  function () {
      // Insert button suite on request page (editing)
      // Precondition:
      //    document ready
      // Uses:
      //    this
      //    >  mw.util.$content
      //    >  .mode
      //    >  .$div
      //    >< .edit.$buttons
      //    .utl.furnish()
      //    jQuery()
      //    jQuery().prepend()
      //    .edit.fetch()
      //    .versions.fire()
      //    .edit.force()
      //    .difflink.fire()
      //    .quiet.fresh()
      // 2013-01-16 PerfektesChaos@de.wikipedia
      var o;
      IUTIL.utl.furnish();
      if ( ! this.$buttons ) {
         this.$buttons  =  $( "<div id='importUtilityButtons' />" );
         o              =  this.fetch();
         if ( o ) {
            if ( o.from  &&  ! o.versions ) {
               IUTIL.versions.fire( o );
            }
         }
         if ( IUTIL.mode === 2 ) {
            this.force( "Export" );
         }
         this.force( "Start" );
         this.force( "Started", "Tic" );
         if ( o ) {
            if ( o.lang ) {
               this.force( "Move" );
               this.force( "Moved", "Tic" );
            }
         }
         this.force( "PageAdapt" );
         this.force( "PageAdapted", "Tic" );
         this.force( "UserNotify" );
         this.force( "UserNotified", "Tic" );
         if ( IUTIL.mode === 1 ) {
            if ( o ) {
               if ( ! o.lang ) {
                  this.force( "Swap" );
               }
            }
         } else {
            this.force( "Done" );
            this.force( "Archive" );
         }
         this.force( "DeleteIssue" );
         IUTIL.$div.prepend( this.$buttons );
         if ( IUTIL.mode === 2  &&  o ) {
            IUTIL.difflink.fire( o.originator );
         }
         IUTIL.quiet.fresh();
      }
   };   // .edit.furnish()



   IUTIL.form.fetch  =  function ( access ) {
      // Get data based upon most recent sessionStorage, and reset
      // Precondition:
      //    access  -- sessionStorage item
      //               object map   { id: value }
      //    "jquery.json" loaded
      // Postcondition:
      //    Returns object if present
      //    sessionStorage item has been cleared
      // Uses:
      //    >< window.sessionStorage
      //    JSON.parse()
      // 2012-12-25 PerfektesChaos@de.wikipedia
      var s,
          r  =  false;
      if ( window.sessionStorage ) {
         s  =  window.sessionStorage.getItem( access );
         if ( s ) {
            if ( typeof s  ===  "string" ) {
               try {
                  r  =  JSON.parse( s );
               } catch ( e ) {
               }
            }
            window.sessionStorage.setItem( access, null );
         }
      }
      return r;
   };   // .form.fetch()



   IUTIL.form.fill  =  function ( assign ) {
      // Fill any form based upon object
      // Precondition:
      //    assign  -- object map   { id: value }
      //    document ready
      // Uses:
      //    >  mw.util.$content
      //    jQuery().find()
      //    jQuery().val()
      // 2012-12-23 PerfektesChaos@de.wikipedia
      var s, $e;
      for ( s in assign ) {
         $e  =  mw.util.$content.find( "#" + s );
         if ( $e.length ) {
            $e.val( assign[ s ] );
         }
      }   // for s in assign
   };   // .form.fill()



   IUTIL.form.freeze  =  function ( access ) {
      // Disable particular control(s) on any form
      // Precondition:
      //    access  -- ID of control
      // Uses:
      //    >  mw.util.$content
      //    jQuery().find()
      //    jQuery().attr()
      //    jQuery().prop()
      // 2013-01-19 PerfektesChaos@de.wikipedia
      var $e  =  mw.util.$content.find( "#" + access );
      if ( $e.length ) {
      // $e.attr( "disabled", null ); // Useless
//TODO   $e.prop( "disabled", true );
      }
   };   // .form.freeze()



   IUTIL.greet.failed  =  function (  ) {
      // Remove user notification form
      // Uses:
      //    >  .$msg
      //    jQuery().empty()
      // 2013-01-16 PerfektesChaos@de.wikipedia
      IUTIL.$msg.empty();
   };   // .greet.failed()



   IUTIL.greet.fire  =  function (  ) {
      // Send user notification
      // Uses:
      //    this
      //    >  .$msg
      //    jQuery().find()
      //    jQuery().val()
      //    .utl.filter()
      //    .notify.fire()
      // 2013-01-21 PerfektesChaos@de.wikipedia
      var s,
          $ta  =  IUTIL.$msg.find( "#greeting" );
      s  =  $ta.val();
      if ( s ) {
         do {
            if ( s.charCodeAt( 0 )  <=  32 ) {
               s  =  s.substr( 1 );
            } else {
               break;   // while s
            }
         } while ( s );
         s  =  IUTIL.utl.filter( s );
      }
      IUTIL.notify.fire( s );
   };   // .greet.fire()



   IUTIL.greet.furnish  =  function () {
      // Create user notification form
      // Uses:
      //    this
      //    >  .$msg
      //    >  .cnf.project.source
      //    >  .cnf.user.greetcols
      //    jQuery().empty()
      //    jQuery().attr()
      //    .edit.fetch()
      //    .quiet.find()
      //    .mw.util.getUrl()
      //    .cnf.feature()
      //    jQuery().append()
      //    .edit.force()
      //    jQuery().append()
      //    known.fire()
      // 2013-01-19 PerfektesChaos@de.wikipedia
      var o     =  IUTIL.edit.fetch(),
          s,
          slot;
      IUTIL.$msg.empty();
      IUTIL.$msg.attr( "style",
                          "margin-top: 1em;"
                       + " margin-bottom: 1em;"
                       + " border: solid 2px #808080;"
                       + " padding: 1em;" );
      if ( o ) {
         slot  =  o.originator;
         if ( IUTIL.quiet.find( slot ) ) {
            s  =  mw.util.getUrl( IUTIL.cnf.project.quiet.source );
            s  =  "<div style='border: solid 1px #800000;"
                           + " color: #800000;"
                           + " padding: 0.5em;"
                           + " font-weight: bold;"
                           + " margin-bottom: 0.5em;'>"
                  +  "<a href='" + s + "' target='_blank'>"
                  +  IUTIL.cnf.feature( "Robinson", false )
                  +  "</a></div>";
            IUTIL.$msg.append( s );
         }
         s  =  "→ <a href='"
                         +  mw.util.getUrl( "User:" + slot )  +  "'"
                + " target='_blank'>" + slot + "</a> &nbsp;";
         IUTIL.$msg.append( s );
         IUTIL.edit.force( "SendNotifier", false, IUTIL.$msg );
         IUTIL.edit.force( "Cancel", false, IUTIL.$msg );
         s  =  ( IUTIL.cnf.user.greetcols ? IUTIL.cnf.user.greetcols
                                          : 80 );
         s  =  "<div style='margin-top: 1em;'>"
               +  IUTIL.cnf.feature( "GreetingAdd", false )
               +  "<br />"
               +  "<textarea id='greeting' rows='4' cols='" + s + "' />"
               +  "</div>";
         IUTIL.$msg.append( s );
         IUTIL.known.fire( slot );
      }
   };   // .greet.furnish()



   IUTIL.known.fault  =  function ( arrived ) {
      // Show API failure on account check
      // Precondition:
      //    arrived  -- JSON info of ajax query, or false
      // Uses:
      //    .batch.failed()
      //    mw.log()
      // Remark: Used as event handler -- 'this' is not IUTIL.known
      // 2013-01-16 PerfektesChaos@de.wikipedia
      IUTIL.batch.failed( false );
      mw.log( {loud:true}, "IUTIL.known.fault()", 2, arrived );
   };   // .known.fault()



   IUTIL.known.found  =  function ( arrived ) {
      // Process API failure on account check
      // Precondition:
      //    arrived  -- JSON info of ajax query, or false
      // Uses:
      //    >  .$div
      //    .cnf.feature()
      //    jQuery()
      //    jQuery().append()
      // Remark: Used as event handler -- 'this' is not IUTIL.known
      // 2013-01-16 PerfektesChaos@de.wikipedia
      var q   =  false;
      if ( arrived ) {
         q  =  arrived.query;
         if ( q ) {
            q  =  q.users;
            if ( q ) {
               q  =  q[ 0 ];
               if ( q ) {
                  if ( ! q.userid ) {
                     q  =  q.name;
                     q  =  "<div style='border: solid 5px #FF0000;"
                                    + " color: #FF0000;"
                                    + " font-weight: bold;"
                                    + " padding: 1em;"
                                    + " margin: 10px;'>"
                                 + IUTIL.cnf.feature( "NoUserName" )
                                                               + ": " + q
                           + "</div>";
                     IUTIL.$div.append( $( q ) );
                  }
               }
            }
         }
      }
   };   // .known.found()



   IUTIL.known.fire  =  function ( account ) {
      // Check whether account is valid
      // Uses:
      //    >  mw.Api
      //    .utl.furnish()
      //    (.known.found)
      //    (.known.fault)
      // 2013-01-16 PerfektesChaos@de.wikipedia
      var q   =  new mw.Api(),
          w   =  { action:  "query",
                   list:    "users",
                   ususers: account,
                   usprop:  "blockinfo" };
      IUTIL.utl.furnish();
      q.get( w ).done( this.found ).fail( this.fault );
   };   // .known.fire()



   IUTIL.mod.fault  =  function ( arrived ) {
      // Postprocess after ajax request failure
      // Precondition:
      //    arrived  -- JSON info of ajax query
      // Uses:
      //    .batch.failed()
      //    .cnf.feature()
      //    mw.log()
      // Remark: Used as event handler -- 'this' is not IUTIL.mod
      // 2012-12-31 PerfektesChaos@de.wikipedia
      IUTIL.batch.failed( "<strong>"
                          + IUTIL.cnf.feature( "*********", false )
                          + "</strong>" );
      mw.log( {loud:true}, "IUTIL.mod.fault()", 2, arrived );
   };   // .mod.fault()



   IUTIL.mod.fetch  =  function () {
      // Retrieve page content for adaption per API
      // Precondition:
      //    WSTM modules have been loaded
      // Uses:
      //    >  mw.Api
      //    >  .mod.subject
      //    .batch.fired()
      //    .edit.fill()
      //    mw.Api.get()
      //    (.mod.found)
      //    (.mod.fault)
      // Remark: Used as event handler -- 'this' is not IUTIL.mod
      // 2012-12-16 PerfektesChaos@de.wikipedia
      var q   =  new mw.Api(),
          w   =  { action:  "query",
                   prop:    "revisions",
                   rvlimit: 1,
                   rvprop:  "content",
                   titles:  IUTIL.mod.subject };
      IUTIL.batch.fired();
      IUTIL.edit.fill( "PageAdapting" );
      q.get( w ).done( IUTIL.mod.found )
                .fail( IUTIL.mod.fault );
   };   // .mod.fetch()



   IUTIL.mod.fine  =  function ( about ) {
      // Page has been written via ajax
      // Precondition:
      //    about  -- message keyword
      // Uses:
      //    .batch.fine()
      //    .edit.fill()
      // 2012-12-31 PerfektesChaos@de.wikipedia
      IUTIL.batch.fine( about );
      IUTIL.edit.fill( about );
   };   // .mod.fine()



   IUTIL.mod.fire  =  function ( apply ) {
      // Initialize page adaption
      // Precondition:
      //    apply  -- Array[2]: namespace number, title
      // Uses:
      //    this
      //    >  .mod.lang
      //    >< .cnf.reSpace
      //    >< mw.libs.WikiSyntaxTextMod
      //     < .mod.space
      //     < .mod.subject
      //     < .mod.wstm
      //    .mod.fetch()
      //    .mod.fired()
      //    mw.loader.load()
      //    (.mod.fired)
      // 2012-12-16 PerfektesChaos@de.wikipedia
      if ( apply[ 0 ]  ===  2 ) {   // user:
         if ( ! IUTIL.cnf.reSpace ) {
            IUTIL.cnf.reSpace  =  new RegExp( " ", "g" );
         }
         this.space    =  "User:";
         this.subject  =  this.space +
                          apply[ 1 ].replace( IUTIL.cnf.reSpace, "_" );
         if ( typeof mw.libs.WikiSyntaxTextMod  !==  "object"   ||
             ! mw.libs.WikiSyntaxTextMod) {
            mw.libs.WikiSyntaxTextMod  =  { };
         }
         this.wstm         =  mw.libs.WikiSyntaxTextMod;
         this.wstm.config  =  { lang: { write:    { linklang:
                                                      IUTIL.mod.lang } },
                                load: { inhibit:  true },
                                mod:  { template: { noop: true } }
                              };
         if ( this.wstm.api ) {
            if ( this.wstm.api.loaded ) {
               this.fetch();
            } else {
               this.wstm.api.load( this.fetch );
            }
         } else {
            this.wstm.config.load.after  =  this.fired;
            mw.loader.load( "//en.wikipedia.org/w/index.php"
                            + "?title=User:PerfektesChaos"
                            + "/js/WikiSyntaxTextMod/r.js"
                            + "&action=raw&ctype=text/javascript"
                            + "&maxage=86400&smaxage=40000",
                            "text/javascript" );
         }
      }
   };   // .mod.fire()



   IUTIL.mod.fired  =  function () {
      // WSTM head module has been loaded
      // Uses:
      //    >  .mod.wstm
      //    .mod.fetch()
      //    (.mod.fetch)
      // Remark: Used as event handler -- 'this' is not IUTIL.mod
      // 2012-12-16 PerfektesChaos@de.wikipedia
      if ( IUTIL.mod.wstm.api.loaded ) {
         IUTIL.mod.fetch();
      } else {
         IUTIL.mod.wstm.api.load( IUTIL.mod.fetch );
      }
   };   // .mod.fired()



   IUTIL.mod.flip  =  function ( access, assign, about, allow, after ) {
      // Store any page content by ajax request
      // Precondition:
      //    access  -- page name
      //    assign  -- text content
      //    about   -- message keyword
      //    allow   -- permit page creation
      //    after   -- function on done
      // Uses:
      //    this
      //    >  mw.Api
      //    >  .type
      //    mw.user.tokens.get()
      //    .cnf.feature()
      //    mw.Api.get()
      //    (.mod.fault)
      // 2012-12-16 PerfektesChaos@de.wikipedia
      var q  =  new mw.Api(),
          w  =  { action:   "edit",
                  token:    mw.user.tokens.get( "csrfToken" ),
                  title:    access,
                  text:     assign,
                  summary:  IUTIL.cnf.feature( about, true )
                            + " / " + IUTIL.type + " " + IUTIL.vsn,
                  nocreate: ! allow };
      q.get( w ).done( after )
                .fail( IUTIL.mod.fault );
   };   // .mod.flip()



   IUTIL.mod.format  =  function ( adjust ) {
      // Postprocess page content after ajax request
      // Precondition:
      //    adjust  -- text content
      // Uses:
      //    this
      //    > .mod.wstm
      //    > .mod.story
      //    .mod.flip()
      // 2012-12-19 PerfektesChaos@de.wikipedia
      var t;
      if ( adjust.indexOf( "{{Importartikel}}" )  <  0 ) {
         t  =  this.mod.wstm.api.textMod( adjust );
         if ( t ) {
            t  =  "{{Importartikel}}\n\n" + t[ 1 ];
            this.flip( this.story,
                       t,
                       "PageAdapted",
                       false,
                       this.formatted );
         }
      } else {
         window.alert( this.type + "\n\n"
                       +  this.cnf.feature( "ErrorAlready", false ) );
      }
   };   // .mod.format()



   IUTIL.mod.formatted  =  function () {
      // Imported page has been saved
      // Uses:
      //    .mod.fine()
      // Remark: Used as event handler -- 'this' is not IUTIL.mod
      // 2012-12-16 PerfektesChaos@de.wikipedia
      IUTIL.mod.fine( "PageAdapted" );
   };   // .mod.formatted()



   IUTIL.mod.found  =  function ( arrived ) {
      // Postprocess page content after ajax request
      // Precondition:
      //    arrived  -- JSON result of ajax query
      // Uses:
      //     < .mod.story
      //    .mod.format()
      //    .mod.fine()
      //    .mod.fault()
      // Remark: Used as event handler -- 'this' is not IUTIL.mod
      // 2012-12-19 PerfektesChaos@de.wikipedia
      var pid  =  false,
          q    =  ( typeof arrived   ===  "object" );
      if ( q ) {
         q  =  arrived.query;
         if ( q ) {
            q  =  q.pages;
            if ( q ) {
               for ( pid in q ) {
                  q  =  q[ pid ];
                  if ( q ) {
                     IUTIL.mod.format( q.revisions[ 0 ][ "*" ] );
                     IUTIL.mod.story  =  q.title;
                  }
                  pid  =  true;
                  break;   // for pid
               }   // for pid in q
            }
         }
      }
      if ( pid === true ) {
         IUTIL.mod.fine( arrived );
      } else {
         IUTIL.mod.fault();
      }
   };   // .mod.found()



   IUTIL.notify.fault  =  function ( arrived ) {
      // Show API failure on message body access
      // Precondition:
      //    arrived  -- JSON info of ajax query
      // Uses:
      //    .cnf.feature()
      //    .batch.failed()
      //    mw.log()
      // Remark: Used as event handler -- 'this' is not IUTIL.notify
      // 2013-01-16 PerfektesChaos@de.wikipedia
      IUTIL.batch.failed( "<strong>"
                          + IUTIL.cnf.feature( "Error" )
                          + " &nbsp; * &nbsp; .notify</strong>" );
      mw.log( {loud:true}, "IUTIL.notify.fault()", 2, arrived );
   };   // .notify.fault()



   IUTIL.notify.fine  =  function () {
      // Show API success on user notification
      // Uses:
      //    >  .$msg
      //    >  .notify.submitter
      //    .batch.fine()
      //    jQuery().append()
      //    .cnf.feature()
      //    mw.util.getUrl()
      //    .edit.fill()
      // Remark: Used as event handler -- 'this' is not IUTIL.notify
      // 2012-12-31 PerfektesChaos@de.wikipedia
      IUTIL.batch.fine( "UserNotified" );
      IUTIL.$msg.append( $( "<span> &nbsp; "
                            + "<a href='"
                                       + mw.util.getUrl(
                                                 IUTIL.notify.submitter )
                               + "' target='_blank'>*</a></span>" ) );
      IUTIL.edit.fill( "UserNotified" );
   };   // .notify.fine()



   IUTIL.notify.fire  =  function ( append ) {
      // Notify user
      // Precondition:
      //    append  -- additional greetings
      // Uses:
      //    this
      //    >  .cnf.project.notify.skeleton
      //    >  .cnf.project.notify.sect
      //    >  .type
      //    >  .vsn
      //    >  mw.Api
      //     < .notify.submitter
      //    .edit.fetch()
      //    .utl.fold()
      //    .utl.factory()
      //    mw.user.tokens.get()
      //    mw.Api.post()
      //    .batch.fired()
      //    .edit.fill()
      //    .cnf.feature()
      //    .edit.failing()
      //    (.notify.fine)
      //    (.notify.fault)
      // 2013-01-16 PerfektesChaos@de.wikipedia
      var p,
          q,
          say  =  IUTIL.cnf.project.notify.skeleton,
          sum  =  IUTIL.cnf.project.notify.sect,
          t,      // translation map
          w    =  IUTIL.edit.fetch();
      if ( w.originator ) {
         t  =  { "l": ( w.lang ? w.lang : "" ),
                 "u": w.originator };
         if ( w.from ) {
            t.s  =  ( w.lang  ?  w.lang + ":" + w.from  :  w.from );
         }
         if ( w.target ) {
            t.t  =  w.target;
            p    =  IUTIL.utl.fold( t.t );
            if ( p && say ) {
               t.n  =  p[ 0 ];
               say  =  say + "|l={{{l}}}"
                           + "|n={{{n}}}"
                           + "|s={{{s}}}"
                           + "|t={{{t}}}"
                           + "|u={{{u}}}";
               if (  append ) {
                  say  =  say + "|g=" + append;
               }
            }
         } else {
            say  =  false;
         }
         this.submitter  =  "User talk:" + w.originator;
         if ( say ) {
            say   =  "{{subst:"
                     + IUTIL.utl.factory( say, t )
                     + "}}~~~~"
                     + "\n<!--" + IUTIL.type + " " + IUTIL.vsn + "-->";
         }
         if ( sum ) {
            sum   =  IUTIL.utl.factory( sum, t );
         }
      } else {
         this.submitter  =  false;
      }
      if ( say && sum && this.submitter ) {
         q  =  new mw.Api();
         w  =  { action:  "edit",
                 token:   mw.user.tokens.get( "csrfToken" ),
                 minor:   false,
                 section: "new",
                 summary: sum,
                 text:    say,
                 title:   this.submitter };
         q.post( w ).done( IUTIL.notify.fine )
                    .fail( IUTIL.notify.fault );
         IUTIL.batch.fired();
         IUTIL.edit.fill( "UserNotifying" );
      } else {
         IUTIL.edit.failing( false );
      }
   };   // .notify.fire()



   IUTIL.proj.fair  =  function () {
      // Process page open action after loading ressources
      // Precondition:
      //    ressources are available
      // Uses:
      //    document
      //    >  .cnf.swift
      //    >  .mode
      //    >  .cnf.project.minutes
      //    jQuery().ready()
      //    .form.fetch()
      //    .zone.fetch()
      //    (.proj.fire)
      // Remark: Used as event handler -- 'this' is not IUTIL.proj
      // 2013-01-23 PerfektesChaos@de.wikipedia
      $( document ).ready( IUTIL.proj.fire );
      IUTIL.form.fetch( IUTIL.cnf.swift );
      if ( IUTIL.mode === 2 ) {
         IUTIL.zone.fetch( IUTIL.cnf.project.minutes );
      }
   };   // .proj.fair()



   IUTIL.proj.fire  =  function () {
      // Perform page open action on request project page
      // Precondition:
      //    document is ready
      // Uses:
      //    >  .options
      //    >  .mode
      //     < .cnf.user
      //    mw.config.get()
      //    .proj.focus()
      //    .edit.fire()
      //    .table.furnish()
      // Remark: Used as event handler -- 'this' is not IUTIL.proj
      // 2013-01-19 PerfektesChaos@de.wikipedia
      var lock  =  mw.config.get( "wgIsArticle" );
      if ( IUTIL.options   &&   typeof IUTIL.options  ===  "object" ) {
         IUTIL.cnf.user  =  IUTIL.options;
      } else {
         IUTIL.cnf.user  =  { };
      }
      if ( IUTIL.mode === 3 ) {
         if ( lock ) {
            IUTIL.table.furnish();
         }
      } else if ( lock ) {
         IUTIL.proj.focus();
      } else {
         IUTIL.edit.fire( false );
      }
   };   // .proj.fire()



   IUTIL.proj.focus  =  function () {
      // Divert all section edit links on request page name to new window
      // Precondition:
      //    Upload request page view
      // Uses:
      //    document.links
      //    >  .mode
      //    .archive.furnish()
      // 2012-12-26 PerfektesChaos@de.wikipedia
      var e, i,
          n  =  document.links.length;
      for ( i = 0;  i < n;  i++ ) {
         e  =  document.links[ i ];
         if ( e.href.indexOf( "&action=edit&section=" ) ) {
            e.target  =  "_blank";
         }
      }   // for i
      if ( IUTIL.mode === 2 ) {
         IUTIL.archive.furnish();
      }
   };   // .proj.focus()



   IUTIL.quiet.fault  =  function ( arrived ) {
      // Show API failure on Robinson list access
      // Precondition:
      //    arrived  -- JSON info of ajax query
      // Uses:
      //    .cnf.feature()
      //    .batch.failed()
      //    mw.log()
      // Remark: Used as event handler -- 'this' is not IUTIL.quiet
      // 2013-01-16 PerfektesChaos@de.wikipedia
      IUTIL.batch.failed( "<strong>"
                          + IUTIL.cnf.feature( "Error" )
                          + " &nbsp; * &nbsp; .quiet</strong>" );
      mw.log( {loud:true}, "IUTIL.quiet.fault()", 2, arrived );
   };   // .quiet.fault()



   IUTIL.quiet.fetch  =  function () {
      // Retrieve data and revision ID of Robinson list storage
      // Postcondition:
      //    Returns revision ID
      // Uses:
      //    this
      //    >  window.localStorage
      //    >  .quiet.storage
      //     < .quiet.story
      // Remark: Used as event handler -- 'this' is not IUTIL.quiet
      // 2013-01-16 PerfektesChaos@de.wikipedia
      var g,
          r  =  -1;
      if ( typeof window.localStorage  ===  "object" ) {
         this.story  =  window.localStorage.getItem( this.storage );
         if ( this.story ) {
            g  =  /\f#([0-9]+)\n/.exec( "\f" + this.story );
            if ( g ) {
               r  =  parseInt( g[1], 10 );
            }
         } else {
            this.story  =  "";
         }
      }
      return r;
   };   // .quiet.fetch()



   IUTIL.quiet.find  =  function ( aware ) {
      // Retrieve data and revision ID of Robinson list storage
      // Precondition:
      //    aware  -- User name in question, may be empty
      // Postcondition:
      //    Returns true if enlisted
      // Uses:
      //    this
      //    >  window.localStorage
      //    >  .quiet.storage
      //    >< .quiet.story
      // Remark: Used as event handler -- 'this' is not IUTIL.quiet
      // 2013-01-16 PerfektesChaos@de.wikipedia
      var r  =  false;
      if ( aware ) {
         if ( typeof window.localStorage  ===  "object" ) {
            this.story  =  window.localStorage.getItem( this.storage );
         }
         if ( this.story ) {
            r  =  ( this.story.indexOf( "\n" + aware + "\n" )  >  0 );
         }
      }
      return r;
   };   // .quiet.find()



   IUTIL.quiet.fresh  =  function () {
      // Update Robinson list on localStorage
      // Uses:
      //    this
      //    >  mw.Api
      //    >  .cnf.project.quiet.source
      //    >  .type
      //     < .quiet.storage
      //    (.quiet.furnish)
      //    (.quiet.fault)
      // 2013-01-16 PerfektesChaos@de.wikipedia
      var q  =  new mw.Api(),
          w  =  { action:       "query",
                  indexpageids: true,
                  prop:         "revisions",
                  rvlimit:      1,
                  rvprop:       "ids|content",
                  titles:       IUTIL.cnf.project.quiet.source };
      this.storage  =  IUTIL.type + "_Robinson";
      q.get( w ).done( this.furnish )
                .fail( this.fault );
   };   // .quiet.fresh()



   IUTIL.quiet.furnish  =  function ( arrived ) {
      // Refresh localStorage with Robinson list page, if changed
      // Precondition:
      //    arrived  -- JSON result of ajax query
      // Uses:
      //    this
      //    >  .quiet.storage
      //     < .quiet.story
      //    >< window.localStorage
      //    .quiet.fetch()
      // Remark: Used as event handler -- 'this' is not IUTIL.quiet
      // 2013-01-16 PerfektesChaos@de.wikipedia
      var k  =  -1,
          q  =  arrived.query,
          s  =  false,
          w;
      if ( q ) {
         q  =  arrived.query;
         if ( q ) {
            w  =  q.pageids;
            if ( w ) {
               k  =  w[ 0 ];
               if ( IUTIL.quiet.fetch() === k ) {
                  k  =  -2;
               }
            }
         }
         if ( q  &&  k > 0 ) {
            q  =  q.pages;
            if ( q ) {
               q  =  q[ k ];
               k  =  -3;
               if ( q ) {
                  q  =  q.revisions;
                  if ( q ) {
                     q  =  q[ 0 ];
                     if ( q ) {
                        s  =  q[ "*" ];
                        k  =  q.revid;
                     }
                  }
               }
            }
         }
      }
      if ( s ) {
         q  =  new RegExp( "\n# *\\[\\[[^:\n]+:([^\n]+)\\]\\]" );
         k  =  "#" + k + "\n\n";
         do {
            w  =  q.exec( s );
            if ( w ) {
               k  =  k  +  w[ 1 ]  +  "\n";
               s  =  s.substr( w.index + w[ 0 ].length);
            }
         } while ( w );
         k  =  k + "|";
         if ( typeof window.localStorage  ===  "object" ) {
            try {
               window.localStorage.setItem( IUTIL.quiet.storage, k );
            } catch ( e ) {
               IUTIL.quiet.story  =  k;
            }
         } else {
            IUTIL.quiet.story  =  k;
         }
      }
   };   // .quiet.furnish()



   IUTIL.rename.fault  =  function ( arrived ) {
      // Show API failure on page move
      // Precondition:
      //    arrived  -- JSON info of ajax query
      // Uses:
      //    .batch.failed()
      //    mw.log()
      // Remark: Used as event handler -- 'this' is not IUTIL.rename
      // 2013-01-01 PerfektesChaos@de.wikipedia
      IUTIL.batch.failed( false );
      mw.log( {loud:true}, "IUTIL.rename.fault()", 2, arrived );
   };   // .rename.fault()



   IUTIL.rename.fine  =  function () {
      // Show API success on page move
      // Uses:
      //    .batch.fine()
      //    .edit.fill()
      // Remark: Used as event handler -- 'this' is not IUTIL.rename
      // 2013-01-01 PerfektesChaos@de.wikipedia
      IUTIL.batch.fine( "Moved" );
      IUTIL.edit.fill( "Moved" );
   };   // .rename.fine()



   IUTIL.rename.fire  =  function () {
      // Move target page
      // Workaround for:   Special:Import target page limitation
      // Uses:
      //    >  mw.Api
      //    >  .type
      //    >  .vsn
      //    .edit.fetch()
      //    .utl.fold()
      //    .cnf.feature()
      //    .batch.failed()
      //    mw.user.tokens.get()
      //    mw.Api.post()
      //    .batch.fired()
      //    .edit.fill()
      //    .edit.failing()
      // (.rename.fine)
      // (.rename.fault)
      // 2013-01-01 PerfektesChaos@de.wikipedia
      var q,
          shift   =  false,
          source  =  false,
          w       =  IUTIL.edit.fetch();
      if ( w ) {
         if ( w.from && w.target ) {
            q  =  IUTIL.utl.fold( w.target );
            if ( q ) {
               source  =  w.from;
               shift   =  w.target;
               if ( q[ 0 ]  ===  2 ) {   // user
                  if ( q[ 2 ] ) {
                     source  =  q[ 2 ] + source;
                     shift   =  shift;
                  } else {
                     shift  =  false;
                  }
               }
            }
         }
      }
      if ( source ) {
         if ( source === shift ) {
            IUTIL.batch.failed( "<strong>"
                                + IUTIL.cnf.feature( "Error" )
                                + " &nbsp; * &nbsp; "
                                + IUTIL.cnf.feature( "MoveToSame" )
                                + "</strong>" );
         } else if ( shift ) {
            q  =  new mw.Api();
            w  =  { action:      "move",
                    token:       mw.user.tokens.get( "csrfToken" ),
                    from:        source,
                    to:          shift,
                    reason:      "Workaround for "
                                 + "[[Special:Import]]"
                                 + " target page limitation * "
                                 + IUTIL.type + " " + IUTIL.vsn,
                    movetalk:    true,
                    noredirect:  true };
            q.post( w ).done( IUTIL.rename.fine )
                       .fail( IUTIL.rename.fault );
            IUTIL.batch.fired();
            IUTIL.edit.fill( "Moving" );
         } else {
            IUTIL.batch.failed( "<strong>"
                                + IUTIL.cnf.feature( "Error" )
                                + " &nbsp; * &nbsp; "
                                + IUTIL.cnf.feature( "MoveSpace" )
                                + "</strong>" );
         }
      } else {
         IUTIL.edit.failing( false );
      }
   };   // .rename.fire()



   IUTIL.spec.fair  =  function () {
      // Process page open action after loading ressources
      // Precondition:
      //    ressources are available
      // Uses:
      //    document
      //    jQuery().ready()
      //    (.spec.fire)
      // Remark: Used as event handler -- 'this' is not IUTIL.spec
      // 2012-12-26 PerfektesChaos@de.wikipedia
      $( document ).ready( IUTIL.spec.fire );
   };   // .spec.fair()



   IUTIL.spec.feed  =  function () {
      // Perform special Import page open action
      // Precondition:
      //    document is ready
      // Uses:
      //    this
      //    >  mw.util.$content
      //    >  .cnf.swift
      //    >< .mode
      //    jQuery().find()
      //    jQuery().eq()
      //    jQuery().attr()
      //    .form.fetch()
      //    jQuery().attr()
      //    .form.fill()
      //    .form.freeze()
      //    .known.fire()
      // 2013-01-17 PerfektesChaos@de.wikipedia
      var o, s, $e;
      o  =  IUTIL.form.fetch( IUTIL.cnf.swift );
      if ( o ) {
         if ( o.interwiki ) {
            s  =  "#mw-import-upload-form";
         } else {
            s           =  "#mw-import-interwiki-form";
            IUTIL.mode  =  -2;
         }
         $e  =  mw.util.$content.find( s );
         if ( $e.length ) {
            $e.attr( "style", "display:none" );
         }
         IUTIL.form.fill( o );
         if ( IUTIL.mode  ===  -1) {
            IUTIL.form.freeze( "frompage" );
            IUTIL.form.freeze( "namespace" );
            IUTIL.form.freeze( "interwiki" );
            IUTIL.form.freeze( "mw-interwiki-rootpage" );
            if ( o.originator ) {
               IUTIL.known.fire( o.originator );
            }
         }
      }
   };   // .spec.feed()



   IUTIL.spec.fire  =  function () {
      // Perform special page open action
      // Precondition:
      //    document is ready
      // Uses:
      //    >  .mode
      //    >  mw.util.$content
      //    .form.freeze()
      //    .spec.feed()
      //    .spec.flush()
      // Remark: Used as event handler -- 'this' is not IUTIL.spec
      // 2012-12-26 PerfektesChaos@de.wikipedia
if (wgUserName==="PerfektesChaos") {
   var sx = '<form method="post" action="Spezial:Importieren&action=submit"id="mw-import-interwiki-form"><p>Wähle aus.</p><input type="hidden" value="submit" name="action" /><input type="hidden" value="interwiki" name="source" /><input type="hidden" value="12345+\" name="editToken" /><select name="interwiki"><option value="de">de</option><option value="en">en</option><option value="sv">sv</option></select> Quell-Wiki/-Seite<input name="frompage" size="50" value="" /><input name="interwikiHistory"id="interwikiHistory" type="checkbox" checked="checked" value="1" /> Alle Versionen dieser Seite importieren <input name="interwikiTemplates" id="interwikiTemplates" type="checkbox" value="1" /> Alle Vorlagen einschließen<select class="namespaceselector" id="namespace" name="namespace"><option value="" selected="">alle</option><option value="0">(Seiten)</option><option value="1">Diskussion</option><option value="2">Benutzer</option><option value="15">Kategorie Diskussion</option></select> Zielnamensraum<input name="log-comment" id="mw-interwiki-comment"type="text" /> Grund <input name="rootpage"id="mw-interwiki-rootpage"type="text" /> Zielstammseite (optional) <input type="submit" value="Importieren" title="[s]" /></form>';
   mw.util.$content.append( $( sx ) );
}
      var s   =  ( IUTIL.mode === -1  ?  "interwikiTemplates"
                                      :  "wpExportTemplates" );
      IUTIL.form.freeze( s );
      if ( IUTIL.mode === -1 ) {
         IUTIL.spec.feed();
      } else {
         IUTIL.spec.flush();
      }
   };   // .spec.fire()



   IUTIL.spec.flush  =  function () {
      // Perform special Export page open action
      // Uses:
      // 2012-12-26 PerfektesChaos@de.wikipedia
// Nur die aktuelle Version der Seite exportieren    id=curonly   false
//  textarea   name="pages"   ausfüllen
   };   // .spec.flush()



   IUTIL.table.factory  =  function ( assign, ahead ) {
      // Create marker comment
      // Precondition:
      //    assign  -- keyword
      //    ahead   -- true: "begin"   else "end"
      // Postcondition:
      //    Return comment
      // 2013-01-19 PerfektesChaos@de.wikipedia
      return  "<!--importUtility " + assign
             + ( ahead ? " begin" : " end" )
             + " -->";
   };   // .table.factory()



   IUTIL.table.fault  =  function ( arrived ) {
      // Show API failure on maintenance page updating
      // Precondition:
      //    arrived  -- JSON info of ajax query, or false
      // Uses:
      //    .batch.failed()
      //    mw.log()
      // Remark: Used as event handler -- 'this' is not IUTIL.table
      // 2013-01-05 PerfektesChaos@de.wikipedia
      IUTIL.batch.failed( false );
      mw.log( {loud:true}, "IUTIL.table.fault()", 2, arrived );
   };   // .table.fault()



   IUTIL.table.feed  =  function ( arrived ) {
      // Retrieve one category member entry for this user
      // Precondition:
      //    arrived  -- JSON info of ajax query, or false, or null
      // Uses:
      //    >  .table.$i
      //    >< .table.item
      //    >< .table.pages
      //    >< .table.query
      //    jQuery().text()
      //    .table.feed()
      //    .table.fetch()
      //    (.table.feed)
      //    (.table.fault)
      // Remark: Used as event handler -- 'this' is not IUTIL.table
      // 2013-01-08 PerfektesChaos@de.wikipedia
      var i, p, q, s,
          t  =  IUTIL.table;
      if ( arrived ) {
         if ( arrived.limits ) {
            t.max            =  arrived.limits.revisions;
            t.query.rvlimit  =  t.max;
         }
         i  =  -1;
         p  =  t.pages[ t.item ];
         q  =  arrived.query;
         if ( q && p ) {
            if ( q.pageids ) {
               i       =  q.pageids[ 0 ];
               p[ 0 ]  =  i;
            }
            q  =  q.pages;
            if ( q  &&  i > 0 ) {
               q  =  q[ i ];
               if ( q ) {
                  q  =  q.revisions;
                  if ( q ) {
                     p[ 5 ]  =  q[ 0 ].timestamp.substr( 0, 10 );
                     i       =  q.length - 1;
                     if ( i ) {
                        p[ 4 ]  =  q[ i ].timestamp.substr( 0, 10 );
                     } else {
                        p[ 4 ]  =  "(1)";
                     }
                  } else {
                     p[ 5 ]  =  "-.-";
                  }
               }
            }
         }
      } else if ( arrived === false ) {   // setup
         t.item   =  -1;
         t.max    =  "max";
         t.query  =  { action:       "query",
                       prop:         "revisions",
                       indexpageids: true,
                       rvlimit:      t.max,
                       rvprop:       "timestamp" };
      }
      t.item++;
      if ( t.item < t.pages.length ) {
         i  =  -9;
         t.$i.text( "#" + t.item );
         s  =  t.pages[ t.item ];
         if ( s ) {
            s  =  s.title;
            if ( s ) {
               t.pages[ t.item ]  =  [ false,     // [0] curid
                                       s,         // [1] user space path
                                       false,     // [2] log entry
                                       false,     // [3] title
                                       false,     // [4] first user edit
                                       false,     // [5] last user edit
                                       false ];   // [6] last edit
               i                  =  s.lastIndexOf( "/" );
            }
         }
         if ( i > 0 ) {
            t.query.titles          =  s;
            t.pages[ t.item ][ 3 ]  =  s.substr( i + 1 );
            s                       =  s.substr( 0, i );
            i                       =  s.indexOf( ":" );
            if ( i > 0 ) {
               t.query.rvuser  =  s.substr( i + 1 );
               q               =  new mw.Api();
               q.get( t.query ).done( t.feed ).fail( t.fault );
            }
         } else {
            IUTIL.table.feed( null );
         }
      } else {
         IUTIL.table.fetch( false );
      }
   };   // .table.feed()



   IUTIL.table.fetch  =  function ( arrived ) {
      // Retrieve logbook entries one by one
      // Precondition:
      //    arrived  -- JSON info of ajax query, or false
      // Uses:
      //    >  .table.$n
      //    >  .table.$i
      //    >< .table.item
      //    >< .table.pages
      //    >< .table.query
      //    jQuery().text()
      //    mw.Api()
      //    .table.fetch()
      //    .table.flow()
      //    (.table.fetch)
      //    (.table.fault)
      // Remark: Used as event handler -- 'this' is not IUTIL.table
      // 2013-01-08 PerfektesChaos@de.wikipedia
      var q,
          t  =  IUTIL.table;
      if ( arrived ) {
         q  =  arrived.query;
         if ( q ) {
            q  =  q.logevents;
            if ( q ) {
               if ( q.length ) {
                  t.pages[ t.item ][ 2 ]  =
                               q[ 0 ].timestamp.substr( 0, 10 )  +  "/*";
               }
            }
         }
      } else if ( arrived === false ) {   // setup
         t.item   =  -1;
         t.query  =  { action:  "query",
                       list:    "logevents",
                       letype:  "import",
                       lelimit: 1,
                       leprop:  "timestamp" };
         t.$n.text( "/" + t.pages.length );
      }
      t.item++;
      if ( t.item < t.pages.length ) {
         t.$i.text( "log " + t.item );
         q  =  t.pages[ t.item ];
         if ( q ) {
            t.query.letitle  =  q[ 1 ];
            q                =  new mw.Api();
            q.get( t.query ).done( t.fetch ).fail( t.fault );
         } else {
            IUTIL.table.fetch( null );
         }
      } else {
         IUTIL.table.flow( false );
      }
   };   // .table.fetch()



   IUTIL.table.fill  =  function ( arrived ) {
      // Retrieve content of maintenance page
      // Precondition:
      //    arrived  -- JSON info of ajax query
      // Uses:
      //     < .table.story
      //    .table.fresh()
      //    .table.fault()
      // Remark: Used as event handler -- 'this' is not IUTIL.table
      // 2013-01-08 PerfektesChaos@de.wikipedia
      var i,
          q  =  arrived.query,
          w  =  q.pageids;
      IUTIL.table.story  =  false;
      if ( w ) {
         i  =  w[ 0 ];
      }
      if ( i ) {
         w  =  q.pages;
         if ( w ) {
            w  =  w[ i ];
            if ( w ) {
               w  =  w.revisions;
               if ( w ) {
                  w  =  w[ 0 ];
                  if ( w ) {
                     IUTIL.table.story  =  w[ "*" ];
                  }
               }
            }
         }
      }
      if ( IUTIL.table.story ) {
         IUTIL.table.fresh();
      } else {
         IUTIL.table.fault();
      }
   };   // .table.fill()



   IUTIL.table.fine  =  function ( arrived ) {
      // Show API success on table page updating
      // Precondition:
      //    arrived  -- JSON info of ajax query, or false
      // Uses:
      //    .batch.fine()
      // Remark: Used as event handler -- 'this' is not IUTIL.table
      // 2013-01-05 PerfektesChaos@de.wikipedia
      IUTIL.batch.fine( "PageUpdated" );
   };   // .table.fine()



   IUTIL.table.finish  =  function ( arrived ) {
      // Retrieve last edit one by one
      // Precondition:
      //    arrived  -- JSON info of ajax query, or false
      // Uses:
      //    >  .table.max
      //    >  .table.$i
      //    >< .table.item
      //    >< .table.pages
      //    >< .table.query
      //    .table.format()
      //    jQuery().text()
      //    (.table.finish)
      //    (.table.fault)
      // Remark: Used as event handler -- 'this' is not IUTIL.table
      // 2013-01-08 PerfektesChaos@de.wikipedia
      var q, s,
          t  =  IUTIL.table;
      if ( arrived ) {
         q  =  arrived.query;
         if ( q ) {
            q  =  q.pages;
            if ( q ) {
               q  =  q[ t.pages[ t.item ][ 0 ] ];
               if ( q ) {
                  q  =  q.revisions;
                  if ( q ) {
                     s  =  q[ 0 ].timestamp.substr( 0, 10 );
                     if ( s === t.pages[ t.item ][ 5 ] ) {
                        s  =  "===";
                     }
                     t.pages[ t.item ][ 6 ]  =  s;
                  }
               }
            }
         }
      } else if ( arrived === false ) {   // setup
         t.item   =  -1;
         t.query  =  { action:  "query",
                       prop:    "revisions",
                       rvlimit: 1,
                       rvprop:  "timestamp" };
      }
      t.item++;
      if ( t.item < t.pages.length ) {
         t.$i.text( "... " + t.item );
         t.query.pageids  =  t.pages[ t.item ][ 0 ];
         q                =  new mw.Api();
         q.get( t.query ).done( t.finish ).fail( t.fault );
      } else {
         IUTIL.table.format();
      }
   };   // .table.finish()



   IUTIL.table.fire  =  function () {
      // Update table on maintenance page
      // Uses:
      //    this
      //    >  mw.Api
      //    >  .cnf.project.table.support
      //     < .table.$i
      //     < .table.$n
      //    .batch.fired()
      //    mw.Api.get()
      //    jQuery().append()
      //    jQuery().find()
      //    (.table.fill)
      //    (.table.fault)
      // 2013-01-08 PerfektesChaos@de.wikipedia
      var q  =  new mw.Api(),
          w  =  { action:       "query",
                  indexpageids: true,
                  prop:         "revisions",
                  rvlimit:      1,
                  rvprop:       "content",
                  titles:       "Project:"
                                + IUTIL.cnf.project.table.support };
      IUTIL.batch.fired( false );
      q.get( w ).done( this.fill )
                .fail( this.fault );
      IUTIL.$msg.append( "<span>&nbsp; &nbsp;</span>"
                         + "<span id='IUTIL-table-i' />"
                         + "<span id='IUTIL-table-n' />" );
      this.$i  =  IUTIL.$msg.find( "#IUTIL-table-i" );
      this.$n  =  IUTIL.$msg.find( "#IUTIL-table-n" );
   };   // .table.fire()



   IUTIL.table.flow  =  function ( arrived ) {
      // Analyze revisions comments for missing log entry
      // Precondition:
      //    arrived  -- JSON info of ajax query, or false
      // Uses:
      //    >  .table.max
      //    >  .table.$i
      //    >< .table.item
      //    >< .table.pages
      //    >< .table.query
      //    .table.flow()
      //    jQuery().text()
      //    .table.finish()
      //    (.table.flow)
      //    (.table.fault)
      // Remark: Used as event handler -- 'this' is not IUTIL.table
      // 2013-01-08 PerfektesChaos@de.wikipedia
      var e, i, j, k, n, p, q,
          t  =  IUTIL.table;
      if ( arrived ) {
         q  =  arrived.query;
         if ( q ) {
            q  =  q.pages;
            if ( q ) {
               q  =  q[ t.pages[ t.item ][ 0 ] ];
               if ( q ) {
                  q  =  q.revisions;
                  if ( q ) {
                     n  =  q.length;
                     if ( n ) {
                        e  =  q[ 0 ];
                        k  =  e.size;
                        for ( i = 1;  i < n;  i++ ) {
                           p  =  q[ i ];
                           j  =  p.size;
                           if ( k - j  ===  0 ) {
                              if ( t.reVsn.test( e.comment ) ) {
                                 t.pages[ t.item ][ 2 ]  =
                                              e.timestamp.substr( 0, 10 )
                                                                 +  "/-";
                                 break;   // for i
                              }
                           }
                           e  =  p;
                           k  =  j;
                        }   // for i
                     }
                  }
               }
            }
         }
      } else if ( arrived === false ) {   // setup
         t.item   =  -1;
         t.query  =  { action:  "query",
                       prop:    "revisions",
                       rvlimit: t.max,
                       rvprop:  "size|comment|timestamp" };
         t.reVsn  =  new RegExp( "^[0-9]+ Versionen\\b" );
      }
      t.item++;
      if ( t.item < t.pages.length ) {
         if ( t.pages[ t.item ][ 2 ] ) {
            IUTIL.table.flow( null );
         } else {
            t.$i.text( "q " + t.item );
            t.query.titles  =  t.pages[ t.item ][ 1 ];
            q               =  new mw.Api();
            q.get( t.query ).done( t.flow ).fail( t.fault );
         }
      } else {
         IUTIL.table.finish( false );
      }
   };   // .table.flow()



   IUTIL.table.fold  =  function ( amount ) {
      // Integrate collected data into page
      // Precondition:
      //    amount  -- wikitable with all entries
      // Uses:
      //    this
      //    >  .type
      //    >  .vsn
      //    >  .cnf.project.table.support
      //    >  .table.$n
      //    >  .table.story
      //    .table.folder()
      //    jQuery().text()
      //    mw.user.tokens.get()
      //    (.table.fine)
      //    (.table.fault)
      // 2013-01-19 PerfektesChaos@de.wikipedia
      var d  =  new Date(),
          i  =  0,
          q  =  new mw.Api(),
          w  =  { action:  "edit",
                  token:   mw.user.tokens.get( "csrfToken" ),
                  minor:   false,
                  summary: "Updated; " + IUTIL.type + " " + IUTIL.vsn,
                  title:   "Project:"
                           + IUTIL.cnf.project.table.support };
      this.folder( "TABLE", amount );
      this.folder( "TIMESTAMP", d.toLocaleString() );
      d  =  0;
      do {
         i  =  amount.indexOf( "\n|-",  i + 2 );
         d++;
      } while ( i > 0 );
      this.folder( "COUNT", d );
      this.$n.text( "UPDATING" );
      w.text  =  this.story;
      q.post( w ).done( IUTIL.table.fine )
                 .fail( IUTIL.table.fault );
   };   // .table.fold()



   IUTIL.table.folder  =  function ( at, against ) {
      // Exchange
      // Precondition:
      //    at  --  wikitable with all entries
      //    against  --  wikitable with all entries
      // Uses:
      //    this
      //    >< .table.story
      //    .table.factory()
      // 2013-01-19 PerfektesChaos@de.wikipedia
      var i, j, s,
          start  =  this.factory( at, true );
      i  =  this.story.indexOf( start );
      if ( i > 0 ) {
         i  +=  start.length;
         s   =  this.factory( at, false );
         j   =  this.story.indexOf( s, i );
         if ( j > 0 ) {
            this.story  =  this.story.substr( 0, i )
                           +  against
                           +  this.story.substr( j );
         }
      }
   };   // .table.folder()



   IUTIL.table.format  =  function () {
      // Format collected data as wikitable
      // Precondition:
      //    arrived  -- JSON info of ajax query, or false
      // Uses:
      //    this
      //    >  .table.max
      //    >  .table.pages
      //    >  .table.$i
      //    >  .table.$n
      //    jQuery().text()
      //    .table.fold()
      // 2013-01-19 PerfektesChaos@de.wikipedia
      var d, e, i, j, u,
          p  =  this.pages,
          n  =  p.length,
          s  =  "";
      this.$i.text( "" );
      this.$n.text( "format" );
      for ( i = 0;  i < n;  i++ ) {
         e  =  p[ i ];
         s  =  s + "\n\n|-\n| <!--" + e[ 0 ] + "-->";    // [0] curid
         d  =  e[ 1 ];
         if ( d ) {   // [1] user space path
            j  =  d.indexOf( ":" );
            if ( j > 1 ) {
               u  =  d.substr( j + 1 );
               j  =  u.indexOf( "/" );
               if ( j > 1 ) {
                  u  =  "'''"  +  u.substr( 0 , j )  +  "''' "
                        +  u.substr( j );
               }
               d  =  "[[" + d + "|" + u + "]]";
            }
         } else {
            d  =  "";
         }
         s  =  s + "\n" + d;
         d  =  e[ 2 ];   // [2] log entry
         s  =  s   +   "\n|"   +   ( d  ?  " " + d  :  "" );
         d  =  e[ 4 ];   // [4] first user edit
         if ( d ) {
            j  =  e[ 2 ];
            if ( j  &&  d.length === 10 ) {
               if ( d  <  j.substr( 0, 10 ) ) {
                  d  =  "<s>" + d + "</s>";
               }
            }
            d  =  " " + d;
         } else {
            d  =  "";
         }
         s  =  s + "\n|" + d;
         d  =  e[ 5 ];   // [5] last user edit
         s  =  s   +   "\n|"   +   ( d  ?  " " + d  :  "" );
         d  =  e[ 6 ];   // [6] last edit
         s  =  s   +   "\n|"   +   ( d  ?  " " + d  :  "" );
         d  =  e[ 3 ];
         if ( d ) {  // [3] title
            s  =  s + "\n| [[" + d + "]]";
         }
      }   // for i
      s  =  s + "\n\n|}\n";
      this.$n.text( "completed" );
      this.fold( s );
   };   // .table.format()



   IUTIL.table.fresh  =  function ( arrived ) {
      // Retrieve list of category members
      // Precondition:
      //    arrived  -- JSON info of ajax query, or false
      // Uses:
      //    >  .cnf.project.table.source
      //    >  .table.$n
      //     < .table.pages
      //     < .table.query
      //    jQuery().text()
      //    .table.feed()
      //    mw.Api.get()
      //    (.table.fresh)
      //    (.table.fault)
      // Remark: Used as event handler -- 'this' is not IUTIL.table
      // 2013-01-08 PerfektesChaos@de.wikipedia
      var p,
          q  =  new mw.Api(),
          t  =  IUTIL.table;
      if ( arrived ) {
         p  =  arrived.query;
         if ( p ) {
            t.pages  =  t.pages.concat( p.categorymembers );
            p        =  arrived[ "query-continue" ];
            if ( p ) {
               p  =  p.categorymembers;
               if ( p ) {
                  p  =  p.cmcontinue;
                  if ( p ) {
                     t.query.cmcontinue  =  p;
                  }
               }
            }
         }
         if ( ! p ) {
            t.query  =  false;
         }
      } else {   // setup
         t.pages  =  [ ];
         t.query  =  { action:       "query",
                       list:         "categorymembers",
                       indexpageids: true,
                       cmlimit:      15,//      "max",
                       cmnamespace:  2,
                       cmprop:       "title|timestamp",
                       cmtitle:      "Category:"
                                     + IUTIL.cnf.project.table.source
                     };
         t.$n.text( "/" + t.pages.length );
      }
      if ( t.query ) {
         q.get( t.query ).done( t.fresh ).fail( t.fault );
      } else {
         t.feed( false );
      }
   };   // .table.fresh()



   IUTIL.table.furnish  =  function () {
      // Equip maintenance page with update control
      // Uses:
      //    >  mw.util.$content
      //    .utl.furnish()
      //    jQuery().find()
      //    jQuery().empty()
      //    .cnf.feature()
      //    jQuery()
      //    jQuery().append()
      // 2013-01-19 PerfektesChaos@de.wikipedia
      var s, $d;
      IUTIL.utl.furnish();
      $d  =  mw.util.$content.find( "#IUTIL-button-update" );
      if ( $d.length ) {
         $d.empty();
         s  =  "<button type='button'"
                    + " id='IUTIL-button-update'"
                    + " onclick='mw.libs.importUtility.table.fire()'>"
            + IUTIL.cnf.feature( "Update" )
            + "</button>";
         $d.append( $( s ) );
      }
   };   // .table.furnish()



   IUTIL.utl.factory   =  function ( adjust, apply ) {
      // Replace placeholders in string
      // Precondition:
      //    adjust  -- base string with possible placeholders  {{{_}}}
      //               may be empty non-string
      //    apply   -- object with key:value assignments
      // Postcondition:
      //    Returns adapted string
      // 2012-12-26 PerfektesChaos@de.wikipedia
      var r  =  adjust,
          re, s;
      if ( r ) {
         if ( r.indexOf( "{{{" )  >=  0 ) {
            for ( s in apply ) {
               re  =  new RegExp( "{{{" + s + "}}}",  "g" );
               r   =  r.replace( re,  apply[ s ] );
            }   // for s in apply
         }
      }
      return r;
   };   // .utl.factory()



   IUTIL.utl.filter  =  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-21 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;
   };   // .utl.filter()



   IUTIL.utl.firm  =  function () {
      // Make signature with time stamp
      // Postcondition:
      //    Return string
      // Uses:
      //    mw.config.get()
      // 2012-12-15 PerfektesChaos@de.wikipedia
      var d  =  new Date(),
          s  =  mw.config.get( "wgUserName" ),
          r  =  "[[User:" + s + "|" + s + "]] " + d.toLocaleString();
      return r;
   };   // .utl.firm()



   IUTIL.utl.fold  =  function ( analyze ) {
      // Split page name into namespace and title
      // Precondition:
      //    analyze  -- page name
      // Postcondition:
      //    Returns Array[3]
      //                 [0]  ns number
      //                 [1]  title
      //                 [2]  root of subpage, terminated by '/'
      // Uses:
      //    >< .cnf.reSpace
      //    mw.config.get()
      // 2012-12-31 PerfektesChaos@de.wikipedia
      var s  =  analyze.replace( /%3A/ig, ":" ),
          r  =  [ 0, s, false ],
          j  =  s.indexOf( ":" ),
          n;
      if ( j > 0 ) {
         if ( ! IUTIL.cnf.reSpace ) {
            IUTIL.cnf.reSpace  =  new RegExp( " ", "g" );
         }
         n  =  s.substr( 0, j ).replace( IUTIL.cnf.reSpace, "_" );
         n  =  mw.config.get( "wgNamespaceIds" )[ n.toLowerCase() ];
         if ( n ) {
            r  =  [ n,  s.substr( j + 1 ),  false ];
            j  =  s.indexOf( "/",   j + 1 );
            if ( j > 0 ) {
               r[ 2 ]  =  s.substr( 0,  j + 1 );
            }
         }
      }
      return r;
   };   // .utl.fold()



   IUTIL.utl.format  =  function ( appoint ) {
      // Format Date object according to ISO 8601 UTC "Z"
      // Precondition:
      //    appoint  -- Date object
      // Postcondition:
      //    Return ISO 8601 string in "Z" time zone
      // 2013-01-05 PerfektesChaos@de.wikipedia
      var r  =  appoint.getUTCFullYear() + "-",
          i  =  appoint.getUTCMonth() + 1;
      if ( i < 10 ) {
			i	=  "0" + i;
      }
      r  =  r + i + "-";
      i  =  appoint.getUTCDate();
      if ( i < 10 ) {
			i	=  "0" + i;
      }
      r  =  r + i + "T";
      i  =  appoint.getUTCHours();
      if ( i < 10 ) {
			i	=  "0" + i;
      }
      r  =  r + i + ":";
      i  =  appoint.getUTCMinutes();
      if ( i < 10 ) {
			i	=  "0" + i;
      }
      r  =  r + i + ":";
      i  =  appoint.getUTCSeconds();
      if ( i < 10 ) {
			i	=  "0" + i;
      }
		return  r + i + "Z";
   };   // .utl.format()



   IUTIL.utl.furnish  =  function () {
      // Insert containers on page
      // Precondition:
      //    document ready
      // Uses:
      //    >  mw.util.$content
      //    >< .$top
      //    >< .$div
      //     < .$msg
      //    mw.util.addCSS()
      //    jQuery()
      //    jQuery().prepend()
      //    jQuery().before()
      // 2013-01-08 PerfektesChaos@de.wikipedia
      mw.util.addCSS( "#siteNotice,"
                      + ".cn-fundraiser-banner,"
                      + "#fundraising"
                      + "{display: none ! important;}" );
      if ( ! IUTIL.$div ) {
         IUTIL.$div  =  $( "<div class='importUtilityDiv' />" );
         if ( ! IUTIL.$top ) {
            IUTIL.$top  =  $( "#mw-content-text" );
            if ( IUTIL.$top.length ) {
               IUTIL.$top.prepend( IUTIL.$div );
            } else {
               IUTIL.$top  =  $( "#bodyContent" );
               if ( ! IUTIL.$top.length ) {
                  IUTIL.$top  =  $( "#article" );
                  if ( ! IUTIL.$top.length ) {
                     IUTIL.$top  =  $( "#content" );
                     if ( ! IUTIL.$top.length ) {
                        IUTIL.$top  =  mw.util.$content;
                     }
                  }
               }
               IUTIL.$top.before( IUTIL.$div );
            }
         }
         IUTIL.$msg  =  $( "<div id='importUtilityMsg'"
                           + " style='display:none;' />" );
         IUTIL.$div.prepend( IUTIL.$msg );
      }
   };   // .utl.furnish()



   IUTIL.versions.fault  =  function ( arrived ) {
      // Show API failure on user notification
      // Precondition:
      //    arrived  -- JSON info of ajax query
      // Uses:
      //    .batch.failed()
      //    mw.log()
      // Remark: Used as event handler -- 'this' is not IUTIL.versions
      // 2012-12-31 PerfektesChaos@de.wikipedia
      IUTIL.batch.failed( false );
      mw.log( {loud:true}, "IUTIL.versions.fault()", 2, arrived );
   };   // .versions.fault()



   IUTIL.versions.fetch  =  function ( arrived ) {
      // Retrieve array length from JSON result
      // Precondition:
      //    arrived  -- JSON result of ajax query
      // Postcondition:
      //    Returns number
      // Uses:
      // 2012-12-31 PerfektesChaos@de.wikipedia
      var i, q,
          r  =  -1;
      if ( typeof arrived   ===  "object" ) {
         q  =  arrived.query;
         if ( q ) {
            i  =  q.pageids[ 0 ];
            q  =  q.pages;
            if ( q  &&  i > 0 ) {
               q  =  q[ i ];
               if ( q ) {
                  r  =  q.revisions.length;
               }
            }
         }
      }
      return r;
   };   // .versions.fetch()



   IUTIL.versions.figure  =  function ( add ) {
      // Display version number in box end edit field
      // Precondition:
      //    add  -- non-null: more versions
      // Uses:
      //    this
      //    >  .versions.number
      //    >  .versions.max
      //    >  .cnf.project.edit.sketch
      //    >  .versions.lazy
      //    >  .$msg
      //    >  .versions.sketch
      //    .cnf.feature()
      //    jQuery().empty()
      //    jQuery().append()
      //    .edit.feed()
      // 2013-01-05 PerfektesChaos@de.wikipedia
      var s    =  "#00A000",
          d    =  new Date(),
          say  =  this.number;
      if ( this.number > this.max ) {
         s    =  "#FF0000";
         say  =  say  +  ( add ? "++" : "" )
                 +  " (&gt;" + this.max + ")";
      }
      say  =  IUTIL.cnf.project.edit.sketch
              + " <strong>" + say + "</strong>";
      if ( ! this.lazy ) {
         IUTIL.$msg.empty();
         IUTIL.$msg.attr( "style",    "border: solid 1px " + s + "; "
                                    + "color: " + s + "; "
                                    + "margin: 3px; "
                                    + "padding: 1em; " );

         IUTIL.$msg.append( "<span>" + say + "</span>" );
      }
      say  =  IUTIL.edit.feed( false )
              +  "\n* "  +  say.replace( /<\/?strong>/g, "'''" )
              + " " + this.sketch + " " + d.toLocaleString();
      IUTIL.edit.feed( say );
   };   // .versions.figure()



   IUTIL.versions.fire  =  function ( about ) {
      // Start version counting
      // Precondition:
      //    about  -- source page information
      //                 .§     -- do not show progress information
      //                 .lang  -- source language other than current
      //                 .from  -- source page
      // Uses:
      //    this
      //    document
      //    >  mw.Api
      //     < .versions.lazy
      //     < .versions.source
      //     < .versions.number
      //    mw.Api.get()
      //    .batch.fired()
      //    mw.util.wikiScript()
      //    (.versions.found)
      //    (.versions.fault)
      // 2013-01-03 PerfektesChaos@de.wikipedia
      var h, p,
          q  =  new mw.Api();
      if ( about[ "§" ] ) {
         this.lazy  =  true;
      } else {
         IUTIL.batch.fired( "Counting" );
      }
      this.source  =  about.from;
      this.number  =  0;
      this.optURL  =  null;
      this.query   =  { action:       "query",
                        indexpageids: true,
                        prop:         "revisions",
                        rvlimit:      "max",
                        titles:       this.source };
      if ( about.lang ) {
         h            =  document.location.hostname;
         p            =  document.location.protocol + "//";
         this.optURL  =  { url:  "//" + about.lang
                                      + h.substr( h.indexOf( "." ) )
                                      + mw.util.wikiScript( "api" )
                         };
         this.query.origin  =  p + h;
      }
      q.get( this.query, this.optURL ).done( this.found )
                                      .fail( this.fault );
   };   // .versions.fire()



   IUTIL.versions.found  =  function ( arrived ) {
      // Some versions counted
      // Precondition:
      //    arrived  -- JSON result of ajax query
      // Uses:
      //    >  .versions.max
      //    >  .versions.lazy
      //    >  .$msg
      //    >< .versions.number
      //    .versions.fetch()
      //    .versions.figure()
      //    jQuery().append()
      //    mw.Api.get()
      //    .cnf.feature()
      //    .batch.failed()
      // Remark: Used as event handler -- 'this' is not IUTIL.versions
      // 2013-01-05 PerfektesChaos@de.wikipedia
      var v  =  IUTIL.versions,
          n  =  v.fetch( arrived ),
          q;
      if ( n > 0 ) {
         v.number  +=  n;
         q          =  arrived[ "query-continue" ];
         if ( v.number > v.max ) {
            v.figure( q );
         } else if ( q ) {
            q  =  q.revisions;
            if ( q ) {
               q  =  q.rvcontinue;
               if ( q ) {
                  v.query.rvcontinue  =  q;
               }
            }
            if ( ! v.lazy ) {
               IUTIL.$msg.append( $( "<span>&nbsp; "
                                     + ( v.number - 1 )
                                     + ", "
                                     + v.number
                                     + ", "
                                     + ( v.number + 1 )
                                     + ", ...</span>" ) );
            }
            if ( q ) {
               q  =  new mw.Api();
               q.get( v.query, v.optURL ).done( v.found )
                                         .fail( v.fault );
            } else {
               mw.log( {loud:true}, "IUTIL.versions.found() ?", 2 );
            }
         } else {
            v.figure( false );
         }
      } else {
         IUTIL.batch.failed( "<strong>"
                             + IUTIL.cnf.feature( "NotFound" )
                             + " &nbsp; * &nbsp; " + v.source
                             + "</strong>" );
         mw.log( {loud:true},
                 "IUTIL.versions.found() Not found", 2, arrived );
      }
   };   // .versions.found()



   IUTIL.zone.factory  =  function ( appoint ) {
      // Retrieve Date object from yyyymmddHHMMSS timestamp in local time
      // Precondition:
      //    appoint  -- yyyymmddHHMMSS string
      // Postcondition:
      //    Return Date object
      // Uses:
      //    this
      //   .zone.fetch()
      // 2013-01-23 PerfektesChaos@de.wikipedia
      var g  =  [ appoint.substr(  0, 4 ),   // yyyy
                  appoint.substr(  4, 2 ),   // mm
                  appoint.substr(  6, 2 ),   // dd
                  appoint.substr(  8, 2 ),   // HH
                  appoint.substr( 10, 2 ),   // MM
                  appoint.substr( 12, 2 )    // SS
                ];
		return  new Date( Date.UTC( parseInt( g[0], 10 ),
                                  parseInt( g[1], 10 )  -  1,
                                  parseInt( g[2], 10 ),
                                  parseInt( g[3], 10 ),
                                  parseInt( g[4], 10 )  -  this.fetch(),
                                  parseInt( g[5], 10 ) ) );
   };   // .zone.factory()



   IUTIL.zone.fetch  =  function ( alt ) {
      // Retrieve timeoffset of local time
      // Precondition:
      //    alt  -- fallback value, if number,  or ignored
      // Postcondition:
      //    Return number; at least 0
      // Uses:
      //    this
      //    >  window.sessionStorage
      //    >  mw.Api
      //    >< .zone.justify
      //    (.zone.found)
      // 2013-01-23 PerfektesChaos@de.wikipedia
      var q, w,
          r  =  0;
      if ( window.sessionStorage ) {
         w  =  window.sessionStorage.getItem( "timeoffset" );
         if ( w ) {
            if ( /\f[0-9]+\f/.test( "\f" + w + "\f" ) ) {
               this.justify  =  parseInt( w, 10 );
            }
         } else {
            q  =  new mw.Api();
            w  =  { action: "query",
                    meta:   "siteinfo" };
            q.get( w ).done( this.found );
         }
      }
      if ( typeof this.justify  !==  "number" ) {
         if ( typeof alt  ===  "number" ) {
            this.justify  =  alt;
         }
      }
      if ( typeof this.justify  ===  "number" ) {
         r  =  this.justify;
      }
      return r;
   };   // .zone.fetch()



   IUTIL.zone.found  =  function ( arrived ) {
      // Evaluate siteinfo query
      // Precondition:
      //    arrived  -- JSON result of ajax query
      // Uses:
      //    >  window.sessionStorage
      //     < .zone.justify
      // Remark: Used as event handler -- 'this' is not IUTIL.zone
      // 2013-01-23 PerfektesChaos@de.wikipedia
      var q  =  arrived;
      if ( q ) {
         q  =  q.query;
         if ( q ) {
            q  =  q.general;
            if ( q ) {
               q  =  q.timeoffset;
               if ( typeof q  ===  "number" ) {
                  this.justify  =  parseInt( q, 10 );
                  if ( window.sessionStorage ) {
                     window.sessionStorage.setItem( "timeoffset", q );
                  }
               }
            }
         }
      }
   };   // .zone.found()



   IUTIL.fire  =  function () {
      // Analyze any page loading; try async ressource loading first
      // Uses:
      //    this
      //    document
      //    >  .cnf.(DBname)
      //    >  .cnf.*.submitTW
      //    >  .cnf.*.submitUP
      //    >  .cnf.*.table.support
      //     < .cnf.project
      //     < .mode
      //    mw.config.get()
      //    mw.loader.using()
      //    (.spec.fair)
      //    (.proj.fair)
      // 2013-01-19 PerfektesChaos@de.wikipedia
      var launch, self, sent;
      switch ( mw.config.get( "wgNamespaceNumber" ) ) {
         case -1 :   // Special
            switch ( mw.config.get( "wgCanonicalSpecialPageName" ) ) {
               case "Import" :
                  this.mode  =  -1;
                  break;
               case "Export" :
                  this.mode  =  -9;
                  break;
            }   // switch wgCanonicalSpecialPageName
            if ( this.mode ) {
               mw.loader.using( [ "jquery.json",
                                  "mediawiki.util" ],
                                this.spec.fair );
            }
            break;
         case 4 :   // Project
            sent    =  mw.config.get( "wgAction" );
            launch  =  ( "|view|edit|submit|".indexOf( sent )  >  0 );
            if ( launch ) {
               if ( sent === "edit" ) {
                  launch  =  ( document.URL.indexOf( "&section=" )
                               >  0 );
               }
               if ( launch ) {
                  self              =  mw.config.get( "wgDBname" );
                  this.cnf.project  =  this.cnf[ self ];
                  if ( this.cnf.project ) {
                     switch ( mw.config.get( "wgTitle" ) ) {
                        case this.cnf.project.submitTW :
                           this.mode  =  1;
                           break;
                        case this.cnf.project.submitUP :
                           this.mode  =  2;
                           break;
                        case this.cnf.project.table.support :
                           this.mode  =  3;
                           break;
                     }   // switch wgTitle
                  }
                  if ( this.mode ) {
                     mw.loader.using( [ "user",
                                        "mediawiki.api",
                                        "mediawiki.api",
                                        "mediawiki.user",
                                        "mediawiki.util" ],
                                      this.proj.fair );
                  }
               }
            }
            break;
      }   // switch wgNamespaceNumber
   };   // .fire()



   if ( ! IUTIL.loaded ) {
      IUTIL.loaded  =  true;
      IUTIL.fire();
      mw.loader.state( "w:de:WP:importUtility", "ready" );
   }
}( mediaWiki, jQuery ) );



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

/// EOF   WP/importUtility/?.js    </nowiki></syntaxhighlight>