User:PerfektesChaos/js/listPageOptions/d.js

/// User:PerfektesChaos/js/listPageOptions/d.js /// 2019-02-04 PerfektesChaos@de.wikipedia // Add specific functionality on watchlists and 'recent changes' // ResourceLoader: compatible; //   dependencies: user, user.options, //                 mediawiki.api, mediawiki.api.watch, //                 mediawiki.user, mediawiki.util //   namespaces:   -1 /// Documentation: w:en:User:PerfektesChaos/js/listPageOptions /// Fingerprint:   #0#0# /// @license GPL [//www.mediawiki.org/w/COPYING] (+GFDL, LGPL, CC-BY-SA) /// /* global window:false, unescape:false                                */ /* jshint forin:false, bitwise:true, curly:true, eqeqeq:true, latedef:true, laxbreak:true, nocomma:true, strict:true, undef:true, unused:true          */

( function ( mw, $ ) {  "use strict";   var Version  =  -6.2,       POpt     =  "listPageOptions";   if ( typeof mw.libs[ POpt ]  !==  "object"   || ! mw.libs[ POpt ] ) {     mw.libs[ POpt ]  =  { };   }   mw.libs[ POpt ].type  =  POpt;   POpt                  =  mw.libs[ POpt ];

// Requires: JavaScript 1.3 //          MediaWiki   1.23            (mw .libs .hook, jQuery core)

if ( typeof POpt.loaded !==  "boolean" ) { // 2018-08-24     POpt.loaded        =  true; POpt.config       =  { "wikidata.bgc": "AFEEEE" }; POpt.disguise     =  { }; POpt.edit         =  { }; POpt.group        =  { "sign": POpt.type + "_groupPg", "show": "groupie", "soft": "enhanced" }; POpt.increm       =  { more: 30 }; POpt.multi        =  { "sign": POpt.type + "_multiPg", "show": "multiple", "soft": "extended" }; POpt.notice       =  { }; POpt.picked       =  { "sign": POpt.type + "_visitedPg", "show": "visited", "soft": "visited" }; POpt.reduce       =  { }; POpt.storage      =  { }; POpt.unwatch      =  { }; POpt.values       =  { }; POpt.config.texts =  { // 2015-10-11        "edit":      {"en": "edit", "de": "Bearbeiten"}, "groupie":  {"en": "Group by pages", "de": "Seitenbezogene\xA0Gruppierung"}, "hide":     {"en": "Hide", "de": "ausblenden"}, "multiple": {"en": "Multiple entries", "de": "Mehrere\xA0Einträge"}, "notice":   {"en": "+\xA0Visited", "de": "+\xA0Gesehen"}, "notice?":  {"en": "Add link for [visited] to every entry", "de": "Link zu 'Gesehen'" + " bei jedem Eintrag"}, "notice!":  {"en": "Mark as visited", "de": "Markiere als 'Gesehen'"}, /*        "ignore":    {"en": "Ignore", "de": "Ignorieren"}, "ignored":  {"en": "Unwatched", "de": "Unbeobachtet"}, "options":  {"en": "Options and notices", "de": "Anzeigeoptionen"}, "show":     {"en": "Show", "de": "einblenden"}, "toggleOff": {"en": "off", "de": "aus"},  // abschalten "toggleOn": {"en": "on", "de": "ein"},  // einschalten "update":   {"en": "meanwhile", "de": "Zwischenzeitlich"}, "unwatch":  {"en": "+\xA0[Unwatch]", "de": "+\xA0Nicht-Beobachten"}, "unwatch?": {"en": "Add link for [unwatch] to every entry", "de": "Link zu 'Nicht beobachten'" + " bei jedem Eintrag"}, "visited":  {"en": "Visited\xA0Pages", "de": "Besuchte\xA0Seiten:"}, "watchPgRE": {"en": "^\\s*([1-9][0-9,]*[^.\n]+[.\n])(.|\n)*$", "de": "^\\s*([1-9][0-9.]*[^.\n]+[.\n])(.|\n)*$"}, "wlnoteRE": {"en": "as of(.+,.+)\\.", "de": "Stand:(.+,.+)Uhr\\."}, "^show":    {"en": "List-Page-Options", "de": "List-Page-Options"}, "^suffix":  {"en": "&#8211;" + " equip watchlist and recent changes" + " with Options", "de": "&#8211;" + " Beobachtungsliste und Letzte Änderungen" + " mit Optionen ausstatten"}, "^support": {"en": "/wiki/" + "User:PerfektesChaos/js/listPageOptions", "de": "/wiki/" + "User:PerfektesChaos/js/listPageOptions"}, "^^lean-show": {"en": "Compress option block" , "de": "Komprimierter Optionsblock"}, "^^learnt-show": {"en": "Enable hiding of visited changes" + " on watchlist", "de": "Möglichkeit zum Verbergen" + " besuchter Änderungen" + " auf der Beobachtungsliste"}, "^^learnt-null": {"en": "not enabled", "de": "keine Möglichkeit"}, "^^learnt-false": {"en": "additional button; preset: show all", "de": "Zusatz-Button; Vorgabe: alle anzeigen"}, "^^learnt-true": {"en": "additional button; preset: hide visited", "de": "Zusatz-Button;" + " Vorgabe: besuchte ausblenden"}, "^^leyo-show": {"en": "Enable hiding of " + " last-edit-your-own on watchlist", "de": "Möglichkeit zum Verbergen" + " eigener letzter Beiträge" + " auf der Beobachtungsliste"}, "^^link-show": {"en": "Button to access this option page", "de": "Schaltknopf," + " um auf diese Optionsseite zu kommen"}, "^^looked-show": {"en": "Enable entries to be marked as 'visited'" + " on watchlist", "de": "Möglichkeit zum Markieren" + " einzelner Änderungen als 'Gesehen'" + " auf der Beobachtungsliste"}, "^^looked-null": {"en": "not enabled", "de": "keine Möglichkeit"}, "^^looked-false": {"en": "on demand", "de": "auf Anforderung"}, "^^looked-true": {"en": "always", "de": "immer"}, "^^lower-show": {"en": "Additional buttons:" + " hide and show option block", "de": "Zusätzliche Knöpfe:" + " Ein- und Ausblenden" + " des Optionsblocks"}, "^^lower-null": {"en": "no additional button", "de": "kein zusätzlicher Knopf"}, "^^lower-false": {"en": "button for hiding", "de": "Knopf zum Ausblenden"}, "^^lower-true": {"en": "hide: button for showing", "de": "Ausblenden; Knopf zum Einblenden"}, "^^luxury-show": {"en": "Additional checkboxes for hide and show", "de": "Zusätzliche Checkboxen" + " zum Ein- und Ausblenden"}, "^^more-show": {"en": "Overlap seconds for incremental watchlist", "de": "Zeitüberschneidung" + " für inkrementelle Beobachtungsliste" + " in Sekunden"}, "^^self":   {"en": "Mark own edit", "de": "Eigene Bearbeitung markieren"} };  // POpt.texts POpt.spooling =  "https://upload.wikimedia.org/wikipedia/commons" + "/d/de/Ajax-loader.gif";  // throbber URL }  // ! .loaded

function fullstop( activity ) { // Stop immediately event propagation // Precondition: //   activity  -- event // 2015-05-12 PerfektesChaos@de.wikipedia if ( typeof activity ===  "object"   &&   activity ) { if ( typeof activity.preventDefault ===  "function" ) { activity.preventDefault; }        if ( typeof activity.stopPropagation  ===  "function" ) { activity.stopPropagation; }     }   }   // fullstop

POpt.config.feature =  function ( apply ) { // Wrap message text access for user or project language // Precondition: //   apply   -- text keyword // Postcondition: //   Return text closest to user language // Uses: //   this //   >  .config.supply //   >  .config.texts //   >< .config.language //   >< .prego //   mw.libs.preferencesGadgetOptions.translation // Remark: To be replaced //        if one day ResourceLoader3 gives access to      //         gadget@translatewiki // 2015-01-11 PerfektesChaos@de.wikipedia var e, r;     if ( typeof this.language  !==  "boolean" ) { if ( typeof POpt.prego !==  "object" ) { if ( typeof mw.libs[ this.supply ] ===  "object" ) { POpt.prego =  mw.libs[ this.supply ]; }        }         if ( typeof POpt.prego  ===  "object" ) { if ( typeof POpt.prego.translation ===  "function" ) { this.language = ( typeof POpt.prego.translation ===  "function" ); }        } else { this.language =  false; }     }      e  =  this.texts[ apply ]; if ( e ) { if ( this.language ) { r =  POpt.prego.translation( e ); } else { r =  e.en; }     } else { r =  "***" + apply + "***"; }     return r;   };   // .config.feature

POpt.config.fetch =  function  { // Retrieve preferences and overwrite presets // Uses: //   >  .prego //   >  .type //    < .lean //    < .learn //    < .leyo //    < .lower //    < .luxury //    < .more //    < .self //   mw.libs.preferencesGadgetOptions.fetch // 2016-05-07 PerfektesChaos@de.wikipedia var scope =  " lean learnt leyo link looked lower luxury" + " more self ", vals  =  POpt.prego.fetch( POpt.type ), s;     for ( s in vals ) { if ( scope.indexOf( " " + s + " " ) >  0 ) { POpt[ s ] =  vals[ s ]; }     }   // for s in vals };  // .config.fetch

POpt.config.fire =  function  { // Prepare ResourceLoader availability // Postcondition: //   preferencesGadgetOptions requested, if not yet defined // Uses: //   this //    <  .config.supply //   mw.loader.getState //   mw.loader.state //   mw.loader.load // 2018-08-24 PerfektesChaos@de.wikipedia var rls, signature; this.supply =  "preferencesGadgetOptions"; signature   =  "ext.gadget." + this.supply; if ( ! mw.loader.getState( signature ) ) { rls =  { }; rls[ signature ] =  "loading"; mw.loader.state( rls ); mw.loader.load( "https://en.wikipedia.org"                        + "/w/index.php?title="                         + "User:PerfektesChaos/js/" + this.supply                         + "/r.js"                         + "&action=raw&bcache=1&maxage=604802"                         + "&ctype=text/javascript",                         "text/javascript" ); }  };   // .config.fire

POpt.config.$flow =  function  { // Create throbber // Postcondition: //   Return jQuery throbber image // Uses: //   >  .spooling //   jQuery // 2015-10-11 PerfektesChaos@de.wikipedia var $r =  $( " " ); $r.attr( { src:   POpt.spooling,                 height: "16",                 alt:    "Ajax" } ); return $r; };  // .config.$flow

POpt.config.form =  function  { // Equip Special:Gadgets page with entry and form // Uses: //   >  .config.texts //   >  .type //   >  .increm.more //   >  .prego //   mw.libs.preferencesGadgetOptions.form // 2016-05-07 PerfektesChaos@de.wikipedia var txt    =  this.texts, dialog = { script: POpt.type, show:   txt[ "^show" ], support: txt[ "^support" ], suffix: txt[ "^suffix" ], opts:   [ { signature: "lean", type:     "checkbox", show:     txt[ "^^lean-show" ], val:      false },                     { signature: "learnt", type:     "radio", show:     txt[ "^^learnt-show" ], poly:     [ { val:  null, show: txt[ "^^learnt-null" ] }, { val: false, show: txt[ "^^learnt-false" ] }, { val: true, show: txt[ "^^learnt-true" ] } ] },                     { signature: "looked", type:     "radio", show:     txt[ "^^looked-show" ], poly:     [ { val:  null, show: txt[ "^^looked-null" ] }, { val: false, show: txt[ "^^looked-false" ] }, { val: true, show: txt[ "^^looked-true" ] } ] },                     { signature: "leyo", type:     "checkbox", show:     txt[ "^^leyo-show" ], val:      false },                     { signature: "lower", type:     "radio", show:     txt[ "^^lower-show" ], val:      null, poly:     [ { val:  null, show: txt[ "^^lower-null" ] }, { val: false, show: txt[ "^^lower-false" ] }, { val: true, show: txt[ "^^lower-true" ] } ] },                     { signature: "luxury", type:     "checkbox", show:     txt[ "^^luxury-show" ], val:      false },                     { signature: "self", type:     "text", show:     txt[ "^^self" ], val:      false },                     { signature: "more", type:     "text", show:     txt[ "^^more-show" ], minimum:  4, maxlength: 4, val:      POpt.increm.more },                     { signature: "link", type:     "checkbox", show:     txt[ "^^link-show" ], val:      false }                   ] };      POpt.prego.form( dialog ); };  // .config.form

POpt.disguise.fetch =  function  { // Initialize Array with leading item links // Postcondition: //   Hidden if matched //   Return true for continuation // Uses: //   this //   >  mw.util.$content //   >  .picked.learn //   >  .letal //   >  .self //   >  .reLeyo //    < .picked.leap //    < .disguise.got //           Array of Arrays //                 [0]  $li  jQuery entry, or $table //                 [1]  page URL //                 [2]  user URL //                 [3]  true: Minor //                 [4]  true: unseen //                 [5]  comment //    < .disguise.list //   jQuery.find //   jQuery.eq //   jQuery.children //   jQuery.attr //   jQuery.css // 2015-01-23 PerfektesChaos@de.wikipedia var leap  =  false, learn =  false, $list =  mw.util.$content.find( "table.mw-enhanced-rc" ), n     =  $list.length, seen  =  "mw-changeslist-line-not-watched",   // visited e, i, low, staff, story, stuff, $e, $li, $trs, $user; POpt.picked.leap =  false; this.got         =  [ ]; this.list        =  ( n === 0 ); if ( this.list ) {  // standard $e =  mw.util.$content.find( "#resultListSort" ); if ( $e.length ) { $e =  $e.find( "ol" ); } else { $e =  mw.util.$content.find( "UL.special" ); }        if ( $e.length ) { $list =  $e.children( "li" ); n     =  $list.length; for ( i = 0; i < n;  i++ ) { $li = $list.eq( i ); if ( POpt.picked.learn ) { learn =  $li.hasClass( seen ); if ( learn ) { POpt.picked.leap =  true; } else { leap =  true; }              }               $e     =  $li.children( "a" ).eq( 0 ); stuff =  $e.attr( "href" ); stuff =  $li.find( "A.mw-changeslist-title"  ) .attr( "href" ); $user =  $li.find( "A.mw-userlink" ); if ( $user.length ) { staff =  $user.attr( "href" ); } else { staff =  false; }              low  =  ( $li.children( ".minoredit" ).length  >  0 ); if ( POpt.letal ) { story =  false; }              this.got.push( [ $li, stuff, staff, low, learn, story ] ); }  // for i            if ( POpt.mode === 1  &&  POpt.self ) { story =  ".mw-changeslist-separator"; $e    =  $( " " ); $e.css( { "font-weight": "bold" }  ); $e.text( POpt.self ); for ( i = 0; i < n;  i++ ) { e     =  this.got[ i ]; staff =  e[ 2 ]; if ( staff ) { if ( this.reLeyo.test( staff ) ) { e[ 0 ].find( story ).after( $e.clone ); }                 }               }   // for i            } }     } else {   // enhanced (grouped) staff =  false; for ( i = 0; i < n;  i++ ) { $li =  $list.eq( i ); if ( POpt.picked.learn ) { learn =  $li.hasClass( seen ); if ( learn ) { POpt.picked.leap =  true; } else { leap =  true; }           }            $trs   =  $li.children( "tbody" ).children( "tr" ); stuff =  $trs.find( "SPAN.mw-title" ).children( "a" ) .attr( "href" ); $e    =  $trs.find( "A.mw-userlink" ); staff =  false; switch ( $e.length ) { case 0 : break; case 1 : staff =  $e.attr( "href" ); break; default : $e =  $trs.find( ".changedby" ) .children( "A.mw-userlink" ); if ( $e.length === 1 ) { staff =  $e.attr( "href" ); } else if ( this.reLeyo ) { $e    =  $trs.eq( 1 ).find( "A.mw-userlink" ); staff =  $e.attr( "href" ); }           }   // switch $e.length if ( this.reLeyo && staff ) { if ( this.reLeyo.test( staff ) ) { $li.hide; }           }            if ( $li ) { low =  ( $trs.children( ".minoredit" ).length  >  0 ); //            if ( POpt.letal  &&  $trs.length == 2 ) { //            }               this.got.push( [ $li, stuff, staff, low, learn, story ] ); }        }   // for i      } POpt.picked.leap =  ( POpt.picked.leap && leap ); };  // .disguise.fetch

POpt.disguise.fiat =  function ( array, abolish ) { // Hiding or show entries // Precondition: //   array    -- filter condition //   abolish  -- true: hide;  false: show again // Uses: //   this //   >  .mode //   .disguise.filter // jQuery.isArray // 2015-11-01 PerfektesChaos@de.wikipedia var i, k, m, n, q, q3, q4; if ( $.isArray( array ) ) { n =  array.length; for ( i = 0; i < n;  i++ ) { q =  array[ i ]; if ( $.isArray( q ) ) { m =  q.length; if ( m > 1 ) { k =  q[ 2 ]; if ( m < 4 ) { q4 =  false; if ( m < 3 ) { q3 =  false; } else { q3 =  q[ 3 ]; }                 } else { q3 =  q[ 3 ]; q4 =  q[ 4 ]; }                 if ( ! k  ||  k === POpt.mode ) { if ( this.filter( q[ 0 ], q[ 1 ], q3, q4, abolish ) ) { break;  // for i                     } }              }            }         }   // for i      } };  // .disguise.fiat

POpt.disguise.filter =  function ( alter, abandon, account, ant, abolish ) { // Hide or show for one entry pattern rule // Precondition: //   alter    -- special page //   abandon  -- namespace page pattern, special page name pattern //   account  -- user pattern //   ant      -- limit to minor edit //   abolish  -- true: hide;  false: show again // Postcondition: //   Returns true if to be aborted, no elements any more //   Elements hidden if matched // Uses: //   this //   >  .picked.learn //   >  .picked.leap //   >  .disguise.list //   >< .disguise.got //   >< .disguise.special //   .format //   .disguise.format // mw.config.get // jQuery.remove // 2015-01-26 PerfektesChaos@de.wikipedia var r =  false, i, l, n, q, rep, reu, s;     if ( alter  ||  abandon  ||  account           ||  ( POpt.picked.learn && POpt.picked.leap ) ) { n =  this.got.length; if ( n ) { if ( alter ||  ! this.list ) { rep =  "/wiki/"; if ( alter ) { if ( ! this.special ) { q =  mw.config.get( "wgFormattedNamespaces" ); if ( q ) { rep =  q[ -1 ]; }                    this.special  =  rep + ":"; }                 rep  =  this.special; }           } else { rep =  "/w(iki/|/index\\.php\\?title=)"; }           if ( abandon ) { s =  POpt.format( abandon ); } else { s =  ""; }           rep  =  new RegExp( rep + s ); reu =  this.format( account ); r =  true; for ( i = 0; i < n;  i++ ) { q =  this.got[ i ]; if ( q ) { l =  false; if ( rep.test( q[ 1 ] ) ) { l =  alter; if ( reu ) { l =  reu.test( q[ 2 ] ); }                    if ( l && ant ) { l =  q[ 3 ]; }                 }                  if ( l ) { if ( abolish ) { q[ 0 ].hide; } else { q[ 0 ].show; }                    this.got[ i ]  =  false; } else { r =  false; }              }            }   // for i         } }     return r;   };   // .disguise.filter

POpt.disguise.fire =  function  { // Start hiding entries // Uses: //   this //   >  .leyo //   >  .self //   >  .picked.learn //   >  .disguise.hide //   >  .disguise.show //   >  .hide //   >  .show //   .disguise.fresh //   .disguise.fetch //   .disguise.fiat // 2015-01-26 PerfektesChaos@de.wikipedia if ( POpt.leyo || POpt.self ) { this.fresh; } else if ( POpt.picked.learn || this.hide || this.show ) { this.fetch; }     if ( this.hide ) { this.fiat( POpt.hide, true ); }     if ( this.show ) { this.fiat( POpt.show, false ); }  };   // .disguise.fire

POpt.disguise.format =  function ( account ) { // Retrieve RegExp for User // Precondition: //   account  -- user pattern, or false // Postcondition: //   Returns RegExp, or false // Uses: //   .format // 2013-04-18 PerfektesChaos@de.wikipedia var r;     if ( account ) { r =  new RegExp( "/w(iki/|/index.php?title=)[^:]+:"                           +  POpt.format( account ) ); } else { r =  false; }     return r;   };   // .disguise.format

POpt.disguise.fresh =  function  { // Prepare "last edit your own" mode // Uses: //   this //    < .reLeyo //   .disguise.format //   .disguise.fetch // mw.config.get // 2013-04-18 PerfektesChaos@de.wikipedia this.reLeyo =  this.format( mw.config.get( "wgUserName" ) ); this.fetch; };  // .disguise.fresh

POpt.edit.fire =  function  { // Equip page with link for editing pages // Precondition: //   document ready // Remark: Used as event handler -- 'this' is not POpt // 2018-05-13 PerfektesChaos@de.wikipedia var $entries =  $( ".mw-htmlform-flatlist-item,"   // OBSOLETING                          + ".oo-ui-fieldLayout-header" ); $entries.each( POpt.edit.furnish ); };  // .edit.fire

POpt.edit.furnish =  function ( address, achieve ) { // Add page edit link to watchlist edit page entry // Precondition: //   address  -- number in superset //   achieve  -- DOM element of list entry // Uses: //   jQuery.find //   jQuery.eq //   jQuery.attr //   jQuery.last //   jQuery.insertAfterappend //   .config.feature // Remark: Used as $.each result -- 'this' is not POpt // 2015-03-21 PerfektesChaos@de.wikipedia var $entry =  $( achieve ), $links =  $entry.find( "a" ), $a     =  $links.eq( 2 ), swift  =  $a.attr( "href" ), $end, $span; $links.attr( { target: "_blank" }  ); if ( swift ) { $end  =  $links.last; swift =  swift.replace( /&action=history/, "&action=edit" ); $a    =  $( "" ); $a.attr( { href:   swift,                     target: "_blank" }  ); $a.text( POpt.config.feature( "edit" ) ); $end.after( $a ); $span =  $( " " ); $span.text( " | " ); $end.after( $span ); }  };   // .edit.furnish

POpt.group.find =  function ( assigned ) { // Analyze URL and page by grabbing; less items than all? // Precondition: //   assigned  -- found URL parameter value  "0", "1", null // Postcondition: //   Initial state of page grouping has been explored // Uses: //   this //   >  mw.util.$content //   >  .group.sign //   >  .group.leaves //   >< .values.ctl2url //   jQuery.find //   mw.user.options.get // 2013-02-27 PerfektesChaos@de.wikipedia var less  =  false, $grab; if ( assigned ) { less =  ( assigned === "1" ); } else { $grab =  mw.util.$content.find( ".mw-enhanced-rc" ); if ( $grab.length ) { less =  true; } else if ( ! this.leaves ) { if ( mw.user.options.get( "usenewrc" ) ) { less =  true; }        }      }      POpt.values.ctl2url[ this.sign ].val  =  ( less ? "1" : "0" ); };  // .group.find

POpt.increm.fire =  function  { // Incremental page refresh // Uses: //   >  .increm.retrieved //   >  .increm.more //   >  .values.script //   >  .special //   >< .more //   >< location //    < .values.ctl2url.days //   mw.config.get //   .values.factory // Remark: Used as event handler -- 'this' is not POpt.increm // 2016-05-09 PerfektesChaos@de.wikipedia var date =  new Date, incr =  ( date - POpt.increm.retrieved )  /  1000, more =  POpt.increm.more, site =  mw.config.get( "wgServer" ); if ( typeof POpt.more === "string"   &&   POpt.more ) { POpt.more =  parseInt( POpt.more, 10 ); }     if ( typeof POpt.more  === "number"   &&   POpt.more > more ) { more =  POpt.more; }     incr  +=  more; POpt.values.ctl2url.days =  false; if ( site.indexOf( "://" ) <  0 ) { site =  window.location.protocol + site; }     window.location  =  site + POpt.values.script + "?title=Special:" + POpt.special + POpt.values.factory + "&days=" +  ( incr / 86400 ); };  // .increm.fire

POpt.increm.furnish =  function ( $around ) { // Precondition: //   $around  -- options block, or false // Postcondition: //   Return jQuery 'update' button, or false // Uses: //   this //   >  mw.util.$content //   >  .type //    < .increm.retrieved //   jQuery //   jQuery.find //   jQuery.attr //   jQuery.click //   jQuery.css //   .config.feature //   jQuery.text //   jQuery.before //   (.increm.fire) // 2015-01-26 PerfektesChaos@de.wikipedia var $r =  false, $box, $e; if ( $around ) { $box =  $around; } else { $box =  mw.util.$content.find( "#mw-watchlist-options" ); }     if ( $box.length ) { POpt.increm.retrieved =  new Date; $e =  $box.find( "br" ).eq( 0 ); if ( $e.length ) { $r =  $( " " ); $r.attr( { id:   POpt.type + "_incrNormal",                        type: "button" }  ) .click( this.fire ) .css( { "margin-left":  "1em",                       "margin-right": "1em" }  ) .text( POpt.config.feature( "update" ) ); $e.before( $r ); }     }      return $r; };  // .increm.furnish

POpt.multi.find =  function ( assigned ) { // Analyze URL; less items than all? // Precondition: //   assigned  -- found URL parameter value  "0", "1", null // Postcondition: //   Initial state of page has been explored // Uses: //   this //   >  .multi.sign //   >< .values.ctl2url //   jQuery.find //   mw.user.options.get // 2013-02-27 PerfektesChaos@de.wikipedia var less =  false; if ( assigned ) { less =  ( assigned === "1" ); } else { if ( mw.user.options.get( "extendwatchlist" ) ) { less =  true; }     }      POpt.values.ctl2url[ this.sign ].val  =  ( less ? "1" : "0" ); };  // .multi.find

POpt.notice.factory =  function  { // Equip one entry with a [visited] link // Postcondition: //   Return true -- continue $.each // Uses: //   >  .unwatch.less //   jQuery //   jQuery.parent //   jQuery.attr //   jQuery.find //   jQuery.each //   (.notice.feed) // Remark: Used as jQuery handler -- 'this' is DOM element // 2015-10-11 PerfektesChaos@de.wikipedia var $e =  $( this ), s;     if ( POpt.unwatch.less ) {   // enhanced $e =  $e.parent; } else {  // standard s =  $e.attr( "class" ); if ( s ) { if ( s.indexOf( "mw-changeslist-line-" ) <  0 ) { $e =  false; }        } else { $e =  false; }     }      if ( $e ) { $e.find( "a" ).each( POpt.notice.feed ); }     return true; };  // .notice.factory

POpt.notice.feed =  function  { // Insert [unwatch] link after history link // Postcondition: //   Return true or false -- continue or break $.each // Uses: //   jQuery //   jQuery.attr //   jQuery.text //   jQuery.click //   jQuery.css //   jQuery.data //   jQuery.append //   jQuery.after //   (POpt.notice.fire) // Remark: Used as jQuery handler -- 'this' is DOM element // 2015-10-11 PerfektesChaos@de.wikipedia var loop =  true, $e   =  $( this ), s    =  $e.attr( "href" ), g, id, $btn, $span; if ( s  &&   s.indexOf( "&action=history" )  >  0 ) { g =  /[?&]title=([^&]+)(&.+)*&curid=([0-9]+)(&.+)?$/.exec( s ); if ( g ) { s     =  g[ 1 ]; id    =  g[ 3 ]; $btn =  $( " " ); $btn.attr( { type: "button",                         title: POpt.config.feature( "notice!" ) } )               .click( POpt.notice.fire ) .css( { "color":         "#006000",                         "font-size":     "85%",                         "font-weight":   "bold",                         "padding-left":  "0",                         "padding-right": "0" }  ) .data( { curid: id,                          title: s }  ) .text( "+" ); $span =  $( " " ); $span.attr( { "class": "curid" + id } ) .text( " | " ) .append( $btn ); $e.after( $span ); loop =  false; }     }      return loop; };  // .notice.feed

POpt.notice.fiat =  function  { // Provide link(s) for visited page // Precondition: //   Watchlist // Uses: //   this //    < .notice.$portlet //   .config.feature //   mw.util.addPortletLink //   (.notice.furnish) // 2015-10-11 PerfektesChaos@de.wikipedia this.$portlet = $( mw.util.addPortletLink( "p-tb", "#",                                       POpt.config.feature( "notice" ), "t-mark-visited", POpt.config.feature( "notice?" ), "v", null ) ); this.$portlet.click( this.furnish ); };  // .notice.fiat

POpt.notice.fine =  function ( arrived, $apply ) { // Normalize entry after successful [visited] // Precondition: //   arrived  -- JSON info of ajax query //   $apply   -- current set of throbber element containers // Uses: //   jQuery.children //   jQuery.each //   (.notice.fix) // Remark: Used as jQuery handler -- 'this' is not POpt.notice // 2015-10-11 PerfektesChaos@de.wikipedia if ( typeof arrived ===  "object"   &&           typeof arrived.invalid  ===  "undefined" ) { $apply.children( "img" ).remove; $apply.each( POpt.notice.fix ); } else { POpt.fault( "notice", arrived, $apply ); }  };   // .notice.fine

POpt.notice.fire =  function  { // Perform visited action // Uses: //   this //   >  mw.util.$content //   >< .notice.api //   jQuery.find //   jQuery.children //   jQuery.hide //   .config.$flow //   jQuery.append //   mw.Api //   mw.Api.postWithToken //   (.notice.fine) //   (.fault) // Remark: Used as jQuery handler -- 'this' is DOM element // 2015-10-11 PerfektesChaos@de.wikipedia var $g =  $( this ), id =  $g.data( "curid" ), $e =  mw.util.$content.find( ".curid" + id ), defaults, promise, s;     if ( $e.length ) { $e.children( "button" ).hide; $e.append( POpt.config.$flow ); if ( typeof POpt.notice.api !==  "object" ) { defaults        =  { parameters: { action: "setnotificationtimestamp" } };           POpt.notice.api  =  new mw.Api( defaults ); }        s        =  unescape( decodeURI( $g.data( "title" ) ) ); promise =  POpt.notice.api.postWithToken( "edit",                                                    { titles: s } ); promise.done( function ( arrived ) {                         POpt.notice.fine( arrived, $e );                       } ) .fail( function ( arrived ) {                         POpt.fault( "notice", arrived, $e );                       } ); }  };   // .notice.fire

POpt.notice.first =  function  { // Provide link(s) for visited page // Precondition: //   Watchlist // Uses: //   this //   >  .looked //    < .notice.$unvisiteds //    < .notice.$portlet //   .notice.furnish //   .notice.fiat // 2015-10-11 PerfektesChaos@de.wikipedia if ( typeof POpt.looked ===  "boolean" ) { this.$unvisiteds =  $( ".mw-changeslist-line-watched" ); if ( this.$unvisiteds.length ) { if ( POpt.looked ) { this.$portlet =  false; this.furnish; } else { this.fiat; }        }      }   };   // .notice.first

POpt.notice.fix =  function  { // Turn one entry into visited and remove throbber // Postcondition: //   Return true -- continue $.each // Uses: //   jQuery.attr // Remark: Used as jQuery handler -- 'this' is DOM element // 2015-10-11 PerfektesChaos@de.wikipedia var $g    =  $( this ).parent, state =  $g.attr( "class" ) .replace( /\bmw-changeslist-line-watched\b/,                               "mw-changeslist-line-not-watched" ); $g.attr( "class", state ); };  // .notice.fix

POpt.notice.furnish =  function ( activity ) { // Equip all entries with an [unwatch] link // Precondition: //   activity  -- event //   Current page is watchlist // Uses: //   >  .$unvisiteds //   >  .$portlet //   fullstop //   jQuery.each //   jQuery.remove //   (.notice.factory) // Remark: Used as event handler -- 'this' is not POpt.notice // 2016-11-11 PerfektesChaos@de.wikipedia fullstop( activity ); POpt.notice.$unvisiteds.each( POpt.notice.factory ); if ( POpt.notice.$portlet ) { POpt.notice.$portlet.remove; }  };   // .notice.furnish

POpt.picked.$factory =  function  { // Create toggle for visited // Postcondition: //   Return toggle text // Uses: //   this //   >  .picked.leap //   >  .type //   >  .values.$POpt //   >  .picked.learning //   >< .picked.$toggle //   jQuery //   jQuery.attr //   jQuery.click //   jQuery.css //   jQuery.append //   .config.feature //   jQuery.text //   (.picked.fire) // 2015-01-11 PerfektesChaos@de.wikipedia var s;     if ( this.leap ) { if ( typeof this.$toggle !==  "object" ) { this.$toggle =  $( " " ); this.$toggle.attr( { id:   POpt.type + "_visited",                                  type: "button" }  ); this.$toggle.click( this.fire ); this.$toggle.css( { "margin-left": "0.5em",                                "margin-right": "0.5em" } ); POpt.values.$POpt.append( this.$toggle ); }        s  =  ( this.learning ? "hide" : "show" ); this.$toggle.text( POpt.config.feature( s ) ); }  };   // .picked.$factory

POpt.picked.fire =  function  { // Execute visited toggling // Uses: //   this //   >  .picked.leap //   >< .picked.learning //   >< .disguise.got //   jQuery.hide //   jQuery.show //   .storage.flush //   .picked.$factory // Remark: Used as event handler -- 'this' is not POpt.reduce // 2015-01-26 PerfektesChaos@de.wikipedia var less =  ( POpt.picked.learning && POpt.picked.leap ), n, i, q;     n  =  POpt.disguise.got.length; for ( i = 0; i < n;  i++ ) { q =  POpt.disguise.got[ i ]; if ( q[ 4 ] ) { if ( less ) { q[ 0 ].hide; } else { q[ 0 ].show; }        }      }   // for i      POpt.storage.flush( "learnt", POpt.picked.learning ); POpt.picked.learning =  ! POpt.picked.learning; POpt.picked.$factory; };  // .picked.fire

POpt.picked.furnish =  function  { // Equip page with link for visited pages // Uses: //   this //   >  .values.$form //   >  .learnt //   >  .picked.show //   >  .picked.leap //   >  .lean //   >  .values.$POpt //    < .picked.learning //    < .picked.$toggle //   .storage.find //   .storage.flush //   jQuery //   jQuery.text //   jQuery.append //   .config.feature //   jQuery.css //   .picked.fire // 2015-01-11 PerfektesChaos@de.wikipedia var s, $span; if ( POpt.values.$form ) { s =  POpt.storage.find( "learnt" ); if ( s ) { this.learning =  ( s === "true" ); } else { this.learning =  POpt.learnt; POpt.storage.flush( "learnt", this.learning ); }        $span  =  $( " " ); $span.text( "\xA0| " ); POpt.values.$POpt.append( $span ); $span =  $( " " ); $span.text( POpt.config.feature( this.show ) ); POpt.values.$POpt.append( $span ); if ( ! this.leap ) { $span =  $( " " ); $span.css( { "color": "#B0B0B0" }  ); $span.text( " ./." ); POpt.values.$POpt.append( $span ); if ( POpt.mode === 2 ) {  // should be excluded anyway this.learning =  false; }        }         if ( POpt.mode === 2  &&  ! POpt.lean ) { POpt.values.$POpt.append( $( " " ) ); }        this.fire; }  };   // .picked.furnish

POpt.reduce.facility =  function  { // Make options and notices visible // Uses: //   >  .reduce.$box //   >  .reduce.$resuscitate //    < .reduce.lower //   jQuery.show //   jQuery.hide //   .storage.flush // Remark: Used as event handler -- 'this' is not POpt.reduce // 2015-01-11 PerfektesChaos@de.wikipedia POpt.reduce.$box.show; POpt.reduce.$resuscitate.hide; POpt.reduce.lower =  false; POpt.storage.flush( "lower", POpt.reduce.lower ); };  // .picked.facility

POpt.reduce.fade =  function  { // Hide options and notices // Uses: //   >  .reduce.$resuscitate //   >  .reduce.$box //    < .reduce.lower //   jQuery.css //   jQuery.show //   jQuery.hide // Remark: Used as event handler -- 'this' is not POpt.reduce // 2015-01-11 PerfektesChaos@de.wikipedia POpt.reduce.$resuscitate.css( { "margin-top": "10px" }  ); POpt.reduce.$resuscitate.show; POpt.reduce.$box.hide; POpt.reduce.lower =  true; POpt.storage.flush( "lower", POpt.reduce.lower ); };  // .picked.fade

POpt.reduce.furnish =  function  { // Equip options area with collapsible handle and prego button // Uses: //   this //   >  .type //   >  .lower //   >  mw.util.$content //   >  .mode //   >  .prego //   >  .link //   >< .$options //    < .reduce.lower //    < .reduce.$box //    < .reduce.stamp //    < .reduce.$resuscitate //    < .reduce.$vanish //   .storage.find //   .storage.flush //   jQuery.find //   .config.feature //   jQuery //   jQuery.attr //   jQuery.css //   jQuery.text //   jQuery.append //   .increm.furnish //   jQuery.clone //   jQuery.click //   jQuery.after //   jQuery.before //   .reduce.fade //   .reduce.facility //   .prego.$button //   (.increm.fire) //   (.reduce.facility) //   (.reduce.fade) // 2015-10-11 PerfektesChaos@de.wikipedia var s =  POpt.storage.find( "lower" ), btnR, got, re, $btn, $div, $span; if ( s ) { this.lower =  ( s === "true" ); } else { this.lower =  POpt.lower; POpt.storage.flush( "lower", this.lower ); }     s          =  ( POpt.mode === 1  ?  "#mw-watchlist-options"                                       :  ".rcoptions" ); this.$box =  mw.util.$content.find( s ); if ( this.$box.length ) { btnR =  { "float":  ( POpt.ltr ? "right" : "left " ) }; btnR[ ( POpt.ltr ? "margin-left" : "margin-right" ) ] =  "8px"; btnR[ ( POpt.ltr ? "margin-right" : "margin-left" ) ] =  "0"; this.$resuscitate =  $( " " ); this.$resuscitate.attr( { id:  POpt.type + "_resuscitate" }  ); this.$resuscitate.css( { "margin-top": "10px" }  ); if ( POpt.mode === 1 ) { s =  this.$box.text; if ( s ) { re  =  new RegExp( POpt.config.feature( "wlnoteRE" ) ); got =  re.exec( s ); if ( got ) { $span =  $( " " ); $span.text( got[ 1 ] ); this.$resuscitate.append( $span ); $btn =  POpt.increm.furnish( this.$box ); if ( $btn ) { $btn =  $btn.clone; $btn.attr( { id:  POpt.type + "_incrShrinked" }  ); $btn.click( POpt.increm.fire ); this.$resuscitate.append( $btn ); }              }            }         }         if ( ! POpt.$options ) { POpt.$options =  this.$box.find( "legend" ); }        if ( POpt.link && POpt.prego ) { $btn =  POpt.prego.$button( POpt.type ); $btn.attr( { id:  POpt.type + "_optPage" }  ); $btn.css( btnR ); $btn.css( { "margin-top": "20px" }  ); POpt.$options.after( $btn ); $div =  $( " " ); $div.css( { "clear": "right" }  ); POpt.$options.after( $div ); }        $btn  =  $( " " ); $btn.attr( { id:   POpt.type + "_optShow",                       type: "button" }  ); $btn.click( POpt.reduce.facility ); $btn.css( ( POpt.ltr ? "margin-left" : "margin-right" ),                  "10px" ); $btn.text( POpt.config.feature( "options" ) ); this.$resuscitate.append( $btn ); this.$box.before( this.$resuscitate ); $btn =  $( " " ); $btn.attr( { id:  POpt.type + "_optHide",                      type: "button" } ); $btn.click( POpt.reduce.fade ); $btn.css( btnR ); $span =  $( " " ); $span.css( { "color":      "#FF0000",                      "font-weight": "bold" } ); $span.text( "X" ); $btn.append( $span ); POpt.$options.after( $btn ); if ( this.lower ) { this.fade; } else { this.facility; }     }   };   // .reduce.furnish

POpt.storage.find =  function ( access ) { // Retrieve volatile configuration from session storage // Precondition: //   access  -- key // Postcondition: //   Return value string, or false // Uses: //   this //   sessionStorage //   >  .type //   >< .stored // 2013-09-06 PerfektesChaos@de.wikipedia var r =  false, s =  "~" + access + "_", i, j;     if ( ! this.stored ) { if ( window.sessionStorage ) { this.stored =  window.sessionStorage.getItem( POpt.type ); }        if ( ! this.stored ) { this.stored =  "~"; }     }      i  =  this.stored.indexOf( s ); if ( i >= 0 ) { j =  this.stored.indexOf( "~",  i + 2 ); if ( j > 0 ) { r =  this.stored.substring( i + s.length,  j ); }     }      return r;   };   // .storage.find

POpt.storage.flush =  function ( access, assign ) { // Remember volatile configuration in session storage // Precondition: //   access  -- key //   assign  -- value // Uses: //   this //   >  .type //   >< .stored // 2013-09-06 PerfektesChaos@de.wikipedia var s =  "~" + access + "_", i, j;     if ( ! this.stored ) { this.stored =  "~"; }     i  =  this.stored.indexOf( s ); s =  s + assign; if ( i < 0 ) { this.stored =  s + this.stored; } else { j =  this.stored.indexOf( "~",  i + 2 ); if ( j < 0 ) { this.stored =  s + "~"; } else { this.stored =  this.stored.substr( 0, i ) + s                            +  this.stored.substr( j ); }     }      if ( window.sessionStorage ) { window.sessionStorage.setItem( POpt.type, this.stored ); }  };   // .storage.flush

POpt.unwatch.factory =  function  { // Equip one entry with an [unwatch] link, if appropriate // Postcondition: //   Return true -- continue $.each // Uses: //   >  .unwatch.less //   jQuery //   jQuery.parent //   jQuery.attr //   jQuery.find //   jQuery.each //   (.unwatch.feed) // Remark: Used as jQuery handler -- 'this' is DOM element // 2013-02-08 PerfektesChaos@de.wikipedia var $e =  $( this ), s;     if ( POpt.unwatch.less ) {   // enhanced $e =  $e.parent; } else {  // standard s =  $e.attr( "class" ); if ( s ) { if ( s.indexOf( "mw-changeslist-line-" ) <  0 ) { $e =  false; }        } else { $e =  false; }     }      if ( $e ) { $e.find( "a" ).each( POpt.unwatch.feed ); }     return true; };  // .unwatch.factory

POpt.unwatch.feed =  function  { // Insert [unwatch] link after history link // Postcondition: //   Return true or false -- continue or break $.each // Uses: //   jQuery //   jQuery.attr //   jQuery.text //   jQuery.click //   jQuery.css //   jQuery.data //   .unwatch.flag //   jQuery.append //   jQuery.after //   (POpt.unwatch.fire) // Remark: Used as jQuery handler -- 'this' is DOM element // 2015-01-11 PerfektesChaos@de.wikipedia var loop =  true, $e   =  $( this ), s    =  $e.attr( "href" ), g, id, $btn, $span; if ( s  &&   s.indexOf( "&action=history" )  >  0 ) { g =  /[?&]title=([^&]+)(&.+)*&curid=([0-9]+)(&.+)?$/.exec( s ); if ( g ) { s     =  g[ 1 ]; id    =  g[ 3 ]; $btn =  $( " " ); $btn.attr( { type: "button" } ) .click( POpt.unwatch.fire ) .css( { "padding-left":  "0",                         "padding-right": "0" }  ) .data( { curid: id,                          leave: true,                          title: s }  ) .text( POpt.unwatch.flag( false ) ); $span =  $( " " ); $span.attr( { "class": "curid" + id } ) .text( " | " ) .append( $btn ); $e.after( $span ); loop =  false; }     }      return loop; };  // .unwatch.feed

POpt.unwatch.fiat =  function  { // Equip watchlist toolbox with link to [unwatch] // Precondition: //   watchlist has been loaded // Uses: //   this //    < .unwatch.$portlet //   .config.feature //   mw.util.addPortletLink //   (POpt.unwatch.furnish) // 2015-10-11 PerfektesChaos@de.wikipedia this.$portlet = $( mw.util.addPortletLink( "p-tb", "#",                                      POpt.config.feature( "unwatch" ), "t-unwatch", POpt.config.feature( "unwatch?" ), "w", null ) ); this.$portlet.click( POpt.unwatch.furnish ); };  // .unwatch.fiat

POpt.unwatch.fine =  function ( arrived, $apply ) { // Insert [watch again] link after successful unwatch // Precondition: //   arrived  -- JSON info of ajax query //   $apply   -- current set of throbber element containers // Uses: //   jQuery.children //   jQuery.remove //   jQuery.each //   .fault //   (.unwatch.fix) // Remark: Used as event handler -- 'this' is not POpt.unwatch // 2015-10-11 PerfektesChaos@de.wikipedia if ( typeof arrived ===  "object"   &&           typeof arrived.invalid  ===  "undefined" ) { $apply.children( "img" ).remove; $apply.each( POpt.unwatch.fix ); } else { POpt.fault( "unwatch", arrived, $apply ); }  };   // .unwatch.fine

POpt.unwatch.fire =  function  { // Perform unwatch action, or undo this // Uses: //   this //   >  mw.util.$content //   >< .unwatch.api //   jQuery.find //   .config.$flow //   mw.Api //   mw.Api.unwatch //   mw.Api.watch //   jQuery.children //   jQuery.hide //   jQuery.append //   (.unwatch.fine) //   (.fault) // Remark: Used as jQuery handler -- 'this' is DOM element // 2016-11-11 PerfektesChaos@de.wikipedia var $g =  $( this ), id =  $g.data( "curid" ), $e =  mw.util.$content.find( ".curid" + id ), promise, subject, submit; if ( $e.length ) { $e.children( "button" ).hide; $e.append( POpt.config.$flow ); subject =  unescape( decodeURI( $g.data( "title" ) ) ); submit  =  ( $g.data( "leave" )  ?  "unwatch"  :  "watch" ); if ( typeof this.api !==  "object" ) { this.api =  new mw.Api; }        promise  =  this.api[ submit ]( subject ); promise.done( function ( arrived ) {                         POpt.unwatch.fine( arrived, $e );                       } ) .fail( function ( arrived ) {                         POpt.fault( "unwatch", arrived, $e );                       } ); }  };   // .unwatch.fire

POpt.unwatch.fix =  function  { // Turn [unwatch] link into [watch again] // Uses: //   jQuery //   jQuery.children //   jQuery.text //   jQuery.data //   .unwatch.flag //   jQuery.show // Remark: Used as event handler -- 'this' is DOM element // 2015-01-11 PerfektesChaos@de.wikipedia var $e   =  $( this ), $btn =  $e.children( "button" ), leave; if ( $btn.length ) { leave =  $btn.data( "leave" ); $btn.css( { "background-color":  ( leave ? "#FFB0B0" : "#B0B0FF" ),                     "padding-left":  "5px",                      "padding-right": "5px" }  ); $btn.data( { leave:  ! leave }  ); $btn.text( POpt.unwatch.flag( leave ) ); $btn.show; }  };   // .unwatch.fix

POpt.unwatch.flag =  function ( again ) { // Retrieve [unwatch] link title, or [watch again] // Precondition: //   again  -- true iff [watch] // Postcondition: //   Return string with [unwatch] link title // 2015-01-11 PerfektesChaos@de.wikipedia return ( again  ?  "/////"  :  String.fromCharCode( 8212 ) ); };  // .unwatch.flag

POpt.unwatch.furnish =  function  { // Equip all entries with an [unwatch] link // Precondition: //   Current page is watchlist // Uses: //   >  mw.util.$content //   >  .group.sign //   >  .values.ctl2url //   >  .unwatch.$portlet //    < .unwatch.less //   jQuery.find //   jQuery.each //   jQuery.remove //   (.unwatch.factory) // Remark: Used as event handler -- 'this' is not POpt.unwatch // 2015-10-11 PerfektesChaos@de.wikipedia var $list =  mw.util.$content.find( "#mw-content-text" ), ctl, seek; if ( $list.length ) { ctl               =  POpt.values.ctl2url[ POpt.group.sign ]; POpt.unwatch.less =  ctl.val; if ( POpt.unwatch.less === "0" ) { POpt.unwatch.less =  false; }        seek  =  ( POpt.unwatch.less  ?  ".mw-title"  :  "li" ); $list.find( seek ).each( POpt.unwatch.factory ); }     POpt.unwatch.$portlet.remove; };  // .unwatch.furnish

POpt.values.factory =  function  { // Make URL from .ctl2url // Postcondition: //   Return query part of URL // Uses: //   this //   >  .values.ctl2url //   .values.fiat // 2013-02-08 PerfektesChaos@de.wikipedia var r =  "", s;     for ( s in this.ctl2url ) { r =  r  +  this.fiat( s ); }  // for s in .ctl2url return r;  };   // .values.factory

POpt.values.fiat =  function ( access ) { // Make URL parameter assignment from '&' until value // Precondition: //   access  -- identifier in .ctl2url // Postcondition: //   Return assignment // Uses: //   this //   >  .values.ctl2url // 2013-02-06 PerfektesChaos@de.wikipedia var par =  this.ctl2url[ access ], r   =  "", s   =  access; if ( par ) { if ( par.val !== undefined ) { if ( par.url ) { s =  par.url; }           if ( par.type === "checkbox" ) { if ( typeof par.val !==  "string" ) { par.val = ( par.val ? "1" : "0" ); }           }            r  =  "&" + s + "=" + par.val; }     }      return r;   };   // .values.fiat

POpt.values.find =  function ( around, adapt ) { // Initialize form and .values fields with hidden input // Precondition: //   around  -- identification of wrapping element //   adapt   -- identification of form // Uses: //   this //   >  mw.util.$content //   >  .lean //   >  .type //    < .values.$wrap //    < .values.$form //    < .values.$POpt //   .values.first //   jQuery.find //   jQuery.each //   jQuery.append //   jQuery.attr //   (.values.found) // 2015-01-11 PerfektesChaos@de.wikipedia var $input, $sep; this.first; this.$wrap =  mw.util.$content.find( around ); if ( this.$wrap.length ) { this.$form =  mw.util.$content.find( adapt ); if ( this.$form.length ) { $input =  this.$form.find( "input" ); $input.each( this.found ); }        if ( POpt.lean ) { $sep =  $( " " ); $sep.text( "\xA0| " ); this.$wrap.append( $sep ); this.$POpt =  $( " " ); } else { this.$POpt =  $( " " ); }        this.$POpt.attr(  { id:  POpt.type + "_extra" }  ); this.$wrap.append( this.$POpt ); } else { this.$form =  false; this.$wrap =  false; this.$POpt =  false; }  };   // .values.find

POpt.values.first =  function  { // Initialize .values component for this application // Uses: //   this //   >  .group.soft //   >  .group.sign //   >  .multi.soft //   >  .multi.sign //   >  .mode //   >< .values.ctl2url // 2013-03-12 PerfektesChaos@de.wikipedia if ( ! this.ctl2url ) { this.ctl2url =  { "associated":      { type: "checkbox" }, "days":           { name: "days", type: false }, // enhanced... Bugzilla:51901, Gerrit:75579 "hideAnons":      { type: "checkbox" }, "hideBots":       { type: "checkbox" }, "hideLiu":        { type: "checkbox" }, "hideMinor":      { type: "checkbox" }, "hideOwn":        { type: "checkbox" }, "hideReviewed":   { type: "checkbox" }, "hideWikibase":   { type: "checkbox" }, // #wb-toggle "nsinvert":       { type: "checkbox", url: "invert" }, "namespace":      { type: "select" } };        this.ctl2url[ POpt.group.sign ]   =  { type: "checkbox", url: POpt.group.soft }; this.ctl2url[ POpt.multi.sign ]  =  { type: "checkbox", url: POpt.multi.soft }; if ( POpt.mode === 2 ) { this.ctl2url.from      =  { type: false }; this.ctl2url.limit     =  { type: false }; this.ctl2url.tagfilter =  { type: "text" }; }     }   };   // .values.first

POpt.values.fix =  function ( access ) { // Adapt URLs of option links to current state // Precondition: //   access  -- identifier in .ctl2url // Uses: //   this //   >  .values.$wrap //   >< .values.$hrefs //   >< .values.ctl2url //    < .values.current //   jQuery.find //   jQuery.each //   (.values.fixing) // 2019-02-04 PerfektesChaos@de.wikipedia if ( ! this.$hrefs ) { if ( this.$wrap ) { this.$hrefs =  this.$wrap.find( "a" ); } else { this.$hrefs =  true; }     }      if ( typeof this.$hrefs  !==  "boolean" ) { this.current =  this.ctl2url[ access ]; if ( ! this.current.url ) { this.current.url =  access; }        this.$hrefs.each( this.fixing ); }  };   // .values.fix

POpt.values.fixing =  function ( at, access ) { // Adapt URL to current state of a control // Precondition: //   at      -- index of element in $.each collection //   access  -- DOM element // Postcondition: //   Return true -- continue $.each // Uses: //   >  .values.current //   >  .values.ctl2url //   >< .values.script //   >< .values.reURL //   mw.config.get //   jQuery.attr // Remark: Used as jQuery handler -- 'this' is DOM element // 2016-10-16 PerfektesChaos@de.wikipedia var got, par, swap, $e; if ( at < 0 ) { $e =  access; } else { $e =  $( access ); }     swap  =  $e.attr( "href" ); if ( swap ) { if ( ! POpt.values.script ) { POpt.values.script =  mw.config.get( "wgScript" ); }        if ( swap.indexOf( POpt.values.script )  <  0 ) { swap =  false; }        if ( swap ) { par =  POpt.values.current; if ( par.val !== undefined ) { if ( ! par.reURL ) { par.reURL =    "([?&]" + par.url + "=)" + "(?:[^&]*)"                               + "(&?.+)?$";                  par.reURL  =  new RegExp( par.reURL ); }              if ( par.type === "checkbox" ) { if ( typeof par.val !==  "string" ) { par.val = ( par.val ? "1" : "0" ); }              }               got  =  par.reURL.exec( swap ); if ( got ) { swap =  swap.replace( par.reURL,                                         "$1" + par.val + "$2" ); } else { swap =  swap + "&" + par.url + "=" + par.val; }              $e.attr(  { href: swap }  ); }        }      }      return true; };  // .values.fixing

POpt.values.flat =  function  { // Compress options by removing line breaks and lines // Uses: //   this //   >  .values.$wrap //   jQuery.find //   jQuery.before //   jQuery.text //   jQuery.remove //   jQuery.show // 2015-01-11 PerfektesChaos@de.wikipedia var $e   =  this.$wrap.find( "br, hr" ), $sep =  $( " " ); $sep.text( " | " ); $e.before( $sep.clone ); $e.remove; this.$wrap.find( "p, form, ul" ).show; };  // .values.flat

POpt.values.flip =  function ( access ) { // Value of a checkbox changed // Precondition: //   access  -- identifier in .ctl2url // Uses: //   this //   >  .values.$form //   >  .mode //   >  .group.sign //   >  .multi.sign //   >< .values.ctl2url //   jQuery.find //   jQuery.attr //   jQuery.prop //   jQuery.val //   jQuery.removeAttr //   .flip //   .values.fix // Remark: Used as event handler -- 'this' is not POpt.group // 2013-02-28 PerfektesChaos@de.wikipedia var par =  this.ctl2url[ access ], s, $e; if ( par ) { if ( ! par.$ctl ) { par.$ctl =  this.$form.find( "#" + access ); }        if ( par.$ctl && par.$ctl.length ) { if ( par.type === "checkbox" ) { s =  par.$ctl.attr( "value" ); if ( s ) { s =  ( s === "0"  ?  "1"  :  "0" ); } else { s =  ( par.$ctl.prop( "checked" )  ?  "1"  :  "0" ); }              par.$ctl.val( s ); if ( s === "0" ) { par.$ctl.removeAttr( "checked" ); }              if ( POpt.mode === 1 ) {   // watchlist only switch ( access ) { case POpt.group.sign : POpt.flip( s, "1", POpt.multi ); break; case POpt.multi.sign : POpt.flip( s, "0", POpt.group ); break; }  // switch access }           } else { s =  par.$ctl.val; }           par.val  =  s;            $e  =  this.$form.find( "#hidden_" + access ); if ( $e.length ) { $e.val( s ); }           this.fix( access ); }     }   };   // .values.flip

POpt.values.found =  function  { // Initialize .values field with hidden input // Precondition: //   this is an input field // Postcondition: //   Return true -- continue $.each // Uses: //   >  .values.ctl2url //   jQuery.attr //   jQuery.val // Remark: Used as jQuery handler -- 'this' is DOM element // 2013-02-06 PerfektesChaos@de.wikipedia var $input =  $( this ), par, sign; if ( $input.attr( "type" ) === "hidden" ) { sign =  $input.attr( "name" ); par  =  POpt.values.ctl2url[ sign ]; if ( par ) { par.val =  $input.val; }     }      return true; };  // .values.found

POpt.values.furnish =  function ( access ) { // Equip visible control with onChange // Precondition: //   access  -- identifier in .ctl2url and of control // Uses: //   this //   >  .values.ctl2url //   >  .values.$form //   >  .slip //   jQuery.find //   jQuery.val //   jQuery.attr // 2015-01-11 PerfektesChaos@de.wikipedia var par =  this.ctl2url[ access ], s;     if ( par ) { if ( ! par.$ctl ) { if ( this.$form ) {  // catch SQL failure par.$ctl =  this.$form.find( "#" + access ); }        }         if ( par.$ctl ) { if ( par.type === "checkbox" ) { s =  ( par.$ctl.prop( "checked" )  ?  "1"  :  "0" ); } else { s =  par.$ctl.val; }           par.val  =  s;            s        =  POpt.slip + ".values.flip('" + access + "');"; par.$ctl.attr( { onchange: s }  ); }     }   };   // .values.furnish

POpt.facilitate =  function  { // Equip options with checkbox for every plain link // Uses: //   this //   >  .mode //   >  .slip //   >  .values.$wrap //   >  .values.ctl2url //   >  .values.$form //   jQuery.find //   jQuery //   jQuery.eq //   jQuery.attr //   jQuery.before //   jQuery.append // 2015-01-11 PerfektesChaos@de.wikipedia var bools =  [ "hideMinor", "hideBots", "hideAnons", "hideLiu", "hideOwn", "hideReviewed" // "hidePatrolled" ],         j       =  ( this.mode === 1  ?  8  :  9 ), n      =  j + bools.length, k      =  0, $set   =  POpt.values.$wrap.find( "a" ), i, par, sign, $e; for ( i = j; i < n;  i++ ) { sign     =  bools[ k ]; par      =  POpt.values.ctl2url[ sign ]; par.$ctl =  $( " " ); par.$ctl.attr( { id:        sign,                           onchange:  POpt.slip                                      + ".values.flip(\"" + sign,                           type:      "checkbox" }  );         if ( par.val ) {            par.$ctl.attr(  { checked: "true" }  );         }         par.$ctl.val( ( par.val ? "1" : "0" ) );         $e  =  $set.eq( i );         $e.attr(  { id:  "link_" + sign }  );         $e.before( par.$ctl );         $e  =  $( " " );         $e.attr(  { id:     "hidden_" + sign,                     name:   sign,                     type:   "hidden",                     value:  ( par.val ? "1'" : "0'" )  }  );         $e.val( ( par.val ? "1" : "0" ) );         POpt.values.$form.append( $e );         k++;      }   // for i   };   // .facilitate

POpt.factory =  function ( assign, ahead ) { // Equip page with 'extended'/'enhanced' toggle checkbox and label // Precondition: //   assign  -- object ( .group. or .multi. ) //              >  .sign //              >  .show //              >  .soft //   ahead   -- true iff leading // Uses: //   this //   >  .values.$form //   >  .values.ctl2url //   >  .special //   >  .lean //   >  .slip //   >  .values.$POpt //   >< .values.script //   mw.config.get //   .config.feature //   .values.factory //   jQuery //   jQuery.prepend //   (.values.flip) // 2015-01-11 PerfektesChaos@de.wikipedia var less, shift, sub, $a, $input, $label, $sep, $span; if ( this.values.$form ) { if ( ! this.values.script ) { this.values.script =  mw.config.get( "wgScript" ); }        less  =  this.values.ctl2url[ assign.sign ].val; if ( less === "0" ) { less =  false; }        shift  =  this.values.script + "?title=Special:" + this.special + this.values.factory; sub   =  "&" + assign.soft + "="; shift =  shift.replace( new RegExp( sub + "?[01]" ),                                  sub  +  ( less ? "0" : "1" )                               );         if ( this.mode === 1 ) { if ( shift.indexOf( "&extended=0" ) >  0 ) { shift =  shift.replace( /&enhanced=1/,                                        "&enhanced=0" ); }           if ( shift.indexOf( "&enhanced=1" )  >  0 ) { if ( shift.indexOf( "&extended=" ) >  0 ) { shift =  shift.replace( /&extended=0/,                                           "&extended=1" ); } else { shift =  shift + "&extended=1"; }           }         }         $label  =  $( " " ); $span  =  $( " " ); $span.text( this.config.feature( assign.show ) +  " (" );         $label.append( $span );         $a  =  $( "" );         $a.attr(  { href: shift }  );         $a.text( this.config.feature( ( less ? "toggleOff" : "toggleOn" ) ) );        $label.append( $a );         $span  =  $( " " );         $span.text( ")" ); $label.append( $span ); this.values.$POpt.prepend( $label ); $input =  $( " " ); $input.attr( { id:        assign.sign,                         name:      assign.soft,                         onchange:  this.slip                                    + ".values.flip('" + assign.sign + "')",                        type:      "checkbox",                         value:     ( less ? "1" : "0" ) } );         if ( less ) { $input.attr( { checked: true }  ); }        this.values.$POpt.prepend( $input ); if ( this.mode === 1 ) { if ( ! this.lean &&  ahead ) { $sep =  $( " " ); } else if ( ! ahead ) { $sep =  $( " " ); $sep.text( "\xA0| " ); }           this.values.$POpt.prepend( $sep ); }     }   };   // .factory

POpt.fault =  function ( action, arrived, $apply ) { // Show API failure on any action // Precondition: //   action   -- keyword of request //   arrived  -- JSON info of ajax query //   $apply   -- current set of throbber element containers // Uses: //   >  mw.util.$content //   >  .type //   jQuery //   jQuery.css //   jQuery.text //   jQuery.empty //   jQuery.append //   mw.log // Remark: Used as jQuery handler -- 'this' is not POpt.notice // 2015-10-11 PerfektesChaos@de.wikipedia var $e =  $( " " ); $e.css( { "border": "#FF0000 2px solid",               "color":  "#FF0000",                "margin": "5px" } ); $e.text( "ERROR" ); $apply.empty; $apply.append( $e ); mw.log( {loud:true},             "." + POpt.type + "." + action + ".fault",              2,              arrived ); };  // .fault

POpt.fiat =  function  { // Equip changes page with controls, analyze by grabbing // Precondition: //   document has been loaded // Uses: //   >  .mode //   >  mw.util.$content //   >  .store //   >  .luxury //   >  .learnt //   >  .lower //   >  .lean //   >  .hide //   >  .letal //   >  .leyo //   >  .self //   >< .$options //    < .ltr //    < .group.leaves //    < .disguise.hide //    < .disguise.show //    < .picked.learn //   jQuery.find //   mw.util.addCSS //   jQuery.hide //   .unwatch.fiat //   .flat //   .values.find //   .facilitate //   .values.furnish //   .disguise.fire //   .picked.furnish //   .reduce.furnish //   .increm.furnish //   .values.flat //   .furnish //   .notice.first // Remark: Used as event handler -- 'this' is not POpt // 2016-05-07 PerfektesChaos@de.wikipedia var sep, store, story, style, suite, $grab, $wd; mw.util.$content.find( ".mw-changeslist-legend" ).hide; POpt.ltr =  ( $( window.document ).find( "html" ).attr( "dir" )                     !==  "rtl" ); switch ( POpt.mode ) { case 1 :  // watchlist sep               =  ".mw-changeslist-separator"; $grab             =  mw.util.$content.find( sep ); POpt.group.leaves =  ( $grab.length > 0 ); if ( POpt.group.leaves ) { POpt.unwatch.fiat; }           story  =  "#mw-watchlist-options"; suite =  "#mw-watchlist-form"; POpt.flat; store =  ".wikibase-edit"; $wd   =  mw.util.$content.find( store ); if ( $wd.length ) { switch ( typeof POpt.store ) { case "boolean": style =  POpt.store; break; case "string": if ( /[0-9A-F]{6}/.test( POpt.store ) ) { style =  POpt.store; break; }  // fall through default: style =  true; }  // switch typeof POpt.store if ( style ===  true ) { style =  POpt.config[ "wikidata.bgc" ]; }              if ( style ) { style =  "{background-color:#" + style + "}"; mw.util.addCSS( store + style ); }           }            break; case 2 :  // rc            POpt.group.leaves  =  true; story             =  ".rcoptions"; suite             =  "form"; break; }  // switch .mode POpt.values.find( story, suite ); if ( POpt.luxury ) { POpt.facilitate; }     POpt.values.furnish( "associated" ); POpt.values.furnish( "nsinvert" ); POpt.values.furnish( "namespace" ); POpt.disguise.hide =  ( typeof POpt.hide  ===  "object"                               &&     POpt.hide ); POpt.disguise.show =  ( typeof POpt.show  ===  "object"                               &&     POpt.show ); POpt.picked.learn  =  ( typeof POpt.learnt  ===  "boolean" ); if ( POpt.disguise.hide ||          POpt.disguise.show ||           POpt.picked.learn ||           POpt.letal ||           POpt.leyo ||           POpt.self ) { POpt.disguise.fire; }     if ( POpt.picked.learn  &&  POpt.mode === 1 ) { POpt.picked.furnish;  // watchlist & visited }     if ( typeof POpt.lower  ===  "boolean" ) { POpt.reduce.furnish; } else if ( POpt.mode === 1 ) {  // watchlist POpt.increm.furnish; }     if ( POpt.lean ) { POpt.values.flat; }     POpt.furnish( POpt.group, false ); if ( POpt.mode === 1 ) {  // watchlist POpt.furnish( POpt.multi, true ); if ( POpt.values.$wrap && POpt.values.$score ) { if ( ! POpt.$options ) { POpt.$options =  POpt.values.$wrap.find( "legend" ); }           POpt.$options.after( POpt.values.$score ); }        POpt.notice.first; }  };   // .fiat

POpt.fire =  function  { // Start processing, if appropriate // Precondition: //   Special page // Uses: //   this //   >  Version //    < .signature //    < .vsn //    < .doc //    < .special //    < .mode //    < .rLoading //   mw.loader.getState //   mw.loader.state //   mw.config.get //   .config.fire //   mw.loader.using //   (.firing) // 2018-08-24 PerfektesChaos@de.wikipedia var env, pages, require, rls; POpt.signature =  "ext.gadget." + POpt.type; POpt.vsn       =  Version; if ( ! mw.loader.getState( POpt.signature ) ) { env      =  mw.config.get( [ "wgCanonicalSpecialPageName",                                       "wgNamespaceNumber" ] ); pages    =  { "Blankpage":     -1, "Gadgets":      -1, "Watchlist":     1, "Recentchanges": 2, "EditWatchlist": 3 }; rls      =  { }; POpt.doc =  "w:en:User:PerfektesChaos/js/" + POpt.type                      + ""; if ( env.wgNamespaceNumber ===  -1 ) { this.special =  env.wgCanonicalSpecialPageName; this.mode    =  pages[ this.special ]; if ( this.mode ) { rls[ this.signature ] =  "loading"; mw.loader.state( rls ); rls[ this.signature ] =  "ready"; this.rLoading =  rls; rls           =  false; this.config.fire; require =  [ "user", "user.options", "mediawiki.user", "mediawiki.util" ]; if ( this.mode === 1 ) { require =  require.concat( [ "mediawiki.api" ] ); }              mw.loader.using( require, this.firing ); }        }         if ( rls ) { rls[ this.signature ] =  "ready"; mw.loader.state( rls ); }     }   };   // .fire

POpt.firing =  function  { // Intermediate loading process step // Precondition: //   MW ressources are available // Uses: //   >  .config.supply //   mw.hook //   (.first) // Remark: Used as event handler -- 'this' is not POpt // 2015-09-12 PerfektesChaos@de.wikipedia mw.hook( POpt.config.supply + ".ready" ).add( POpt.first ); };  // .firing

POpt.first =  function ( attributes ) { // Start processing // Precondition: //   attributes  -- preferencesGadgetOptions application object //   All ressources are available // Uses: //   >  .type //   >  .mode //   >  .rLoading //    < .prego //    < .slip //   .config.fetch //   jQuery.ready //   .config.form //   mw.loader.state //   mw.hook //   (.fiat) //   (.edit.fire) // Remark: Used as event handler -- 'this' is not POpt // 2018-08-26 PerfektesChaos@de.wikipedia POpt.prego =  attributes; POpt.slip  =  "mw.libs." + POpt.type; if ( POpt.mode > 0 ) { if ( POpt.prego ) { POpt.config.fetch; }        if ( POpt.mode < 3 ) { $( POpt.fiat ); } else { $( POpt.edit.fire ); }     } else if ( POpt.prego ) { POpt.config.form; }     mw.loader.state( POpt.rLoading ); mw.hook( POpt.type + ".ready" ).fire( POpt ); };  // .first

POpt.flat =  function  { // Remove watchlist information // Uses: //   >  mw.util.$content //    < .values.$score //   jQuery.find //   jQuery.children //   .config.feature //   jQuery.text //   jQuery.remove // 2015-01-11 PerfektesChaos@de.wikipedia var $e =  mw.util.$content.find( "#mw-content-text" ), re, s;     if ( $e.length ) { $e =  $e.children( "p" ); if ( $e.length ) { re =  new RegExp( POpt.config.feature( "watchPgRE", false ) ); s  =  $e.text.replace( re, "$1" ); if ( s ) { $e.remove; POpt.values.$score =  $( " " ); POpt.values.$score.text( s + "\xA0| " ); // update }        }      }   };   // .flat

POpt.flip =  function ( alter, allow, assign ) { // Coordinate multiple and grouped watchlist entries // Precondition: //   alter   -- just set parameter value,  "0" or "1" //   allow   -- required parameter value,  "0" or "1" //   assign  -- corresponding object to be updated // Uses: //   this //   >  .values.$form //   >< .values.ctl2url //   jQuery.find //   jQuery.click // 2013-02-28 PerfektesChaos@de.wikipedia var co, s;     if ( alter === allow ) { s  =  assign.sign; co =  this.values.ctl2url[ s ]; if ( co ) { if ( co.val !== allow ) { if ( ! co.$ctl ) { if ( this.values.$form ) { co.$ctl =  this.values.$form.find( "#" + s ); }              }               if ( co.$ctl ) { co.$ctl.click; }           }         }      }   };   // .flip

POpt.format =  function ( access ) { // Encode URL part string regexp conditionally for Wiki // Precondition: //   access  -- string, part of URL // Postcondition: //   Return string, ready for URL // Uses: //   this //   >< .sp2_ // 2013-03-08 PerfektesChaos@de.wikipedia var r =  access, i, k, n, s;     if ( r ) { if ( access.indexOf( "%" ) <  0 ) { n =  access.length; r =  ""; for ( i = n - 1; i >= 0;  i-- ) { k =  access.charCodeAt( i ); s =  String.fromCharCode( k ); if ( k > 127 ) { s =  encodeURI( s ); }              r  =  s + r;            }   // for i-- s =  mw.util.wikiUrlencode( r ); } else { if ( ! this.sp2_ ) { this.sp2_ =  new RegExp( " ", "g" ); }           r  =  r.replace( this.sp2_, "_" ); }     }      return r;   };   // .format

POpt.furnish =  function ( assign, ahead ) { // Equip page with additional labeled control // Precondition: //   assign  -- object ( .group. or .multi. ) //              >  .soft //              >  .sign //              .find //   ahead  -- true iff leading //   document has been loaded // Uses: //   this //   mw.util.getParamValue //   .values.fix //   .factory // 2013-02-27 PerfektesChaos@de.wikipedia var set =  mw.util.getParamValue( assign.soft ); assign.find( set ); POpt.values.fix( assign.sign ); this.factory( assign, ahead ); };  // .furnish

POpt.fire; }( window.mediaWiki, window.jQuery ) );

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

/// EOF  listPageOptions/d.js