User:PerfektesChaos/js/clickDivertimento/d.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/// User:PerfektesChaos/js/clickDivertimento/d.js
/// 2019-07-24 PerfektesChaos@de.wikipedia
// Divert links into other browser window or tab
// ResourceLoader:  compatible;
//                  dependencies: user, user.options
/// Fingerprint: #0#0#
/// @license: CC-by-sa/4.0
/// Documentation: [[w:en:User:PerfektesChaos/js/clickDivertimento]]
/// <nowiki>
/* global window: false, MutationObserver: 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  =  -1.9,
       CDV      =  "clickDivertimento",
       Config   =  { },
       Prego    =  { };
   if ( typeof mw.libs[ CDV ]  !==  "object"   ||   ! mw.libs[ CDV ] ) {
      mw.libs[ CDV ]  =  { };
   }
   mw.libs[ CDV ].type  =  CDV;
   CDV                  =  mw.libs[ CDV ];
   if ( typeof CDV.vsn  !==  "number" ) {
      // 2014-02-20
      CDV.vsn        =  Version;
      CDV.signature  =  "ext.gadget." + CDV.type;
      CDV.support    =  "User:PerfektesChaos/js/" + CDV.type;
      CDV.doc        =  "[[w:en:" + CDV.support + "]]";
      Config.pages   =  [ "en", "de" ];
      Config.texts   =  {
         // 2014-02-20 PerfektesChaos@de.wikipedia
         "^show":   {"en": "Click-Divertimento",
                     "de": "Click-Divertimento"},
         "^suffix": {"en": "&#8211; Open links in new browser window",
                     "de": "&#8211; Links"
                           + " in neuem Browserfenster öffnen"},
         "^^large": {"en": "Include more list pages",
                     "de": "Weitere Seiten mit Listen einschließen"},
         "^^leave": {"en": "All external links shall be opened"
                           + " in new browser window",
                     "de": "Alle externen Links"
                           + " in neuem Browserfenster öffnen"},
         "^^mode":  {"en": "Create entirely new window",
                     "de": "Völlig neues Fenster öffnen"},
         "^^mode0": {"en": "For all diverted targets",
                     "de": "Immer, wenn ein Link beeinflusst wird"},
         "^^mode1": {"en": "Shared windows for the same tasks",
                     "de": "Wiederbenutzung für gleiche Aufgaben"},
         "^^mode2": {"en": "All in the same different window",
                     "de": "Alle im selben Zweitfenster"}
      };   // .texts
   }



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



   function fiat() {
      // Handle particular link element
      // Uses:
      //    >  this
      //    >  Config.source
      //    >  Config.shift
      //    >  Config.kind
      //    >  Config.mode
      //    >  Config.targets
      // 2019-07-24 PerfektesChaos@de.wikipedia
      /* jshint validthis:true                                         */
      var $hype = $( this ),
          src   = $hype.attr( "href" ),
          k     = src.charCodeAt( 0 ),
          cond, conds, i, shift;
      if ( k === 35 ) {
         $hype = false;
      } else {
         i = src.indexOf( "#" );
         if ( i > 0   &&
              src.substr( 0, i )  ===  Config.source ) {
            $hype = false;
         }
         if ( $hype   &&
              k !== 47   &&
              src.indexOf( "//" )  <  0 ) {
            $hype = false;
         }
      }
      if ( $hype ) {
         shift = Config.shift;
         if ( Config.kind === 1 ) {
            if ( $hype.hasClass( "external" ) ) {
               if ( Config.mode ) {
                  shift = "WikiExtern";
               }
            } else {
               shift = false;
            }
         }
         if ( typeof Config.targets  ===  "object"  ) {
            for ( k in Config.targets ) {
               conds = Config.targets[ k ];
               for ( i = 0;  i < conds.length;  i++ ) {
                  cond = conds[ i ];
                  switch ( typeof cond ) {
                     case "string" :
                        if ( src.indexOf( cond )  >=  0 ) {
                           conds = false;
                        }
                        break;
                     case "object" :
                        if ( cond.test( src ) ) {
                           conds = false;
                        }
                        break;
                  }   // switch typeof
                  if ( ! conds ) {
                     break;   // for i
                  }
               }   // for i
               if ( ! conds ) {
                  shift = k;
                  break;   // for k
               }
            }   // for k
         }
         if ( shift  &&  ! $hype.attr( "target" ) ) {
            $hype.attr( "target", shift );
         }
      }
   }   // fiat()



   function fit() {
      // Handle particular form element
      // Uses:
      //    >  this
      //    >  Config.shift
      // 2019-07-24 PerfektesChaos@de.wikipedia
      /* jshint validthis:true                                         */
      var $hype = $( this );
      if ( ! $hype.attr( "target" ) ) {
         $hype.attr( "target", Config.shift );
      }
   }   // fit()



   function flyout() {
      // Handle suggestions elements
      // Uses:
      //    (fit)
      // 2016-04-03 PerfektesChaos@de.wikipedia
      var suggestion = "a.mw-searchSuggest-link",
          observer, $div;
      if ( typeof MutationObserver  ===  "function" ) {
         $div = $( ".suggestions-results" );
         if ( $div.length ) {
            observer = new MutationObserver(
                                 function( mutations ) {
                                    mutations.forEach(
                                          function() {
                                             $( suggestion ).each( fit );
                                          } );
                                 } );
            observer.observe( $div.get( 0 ),
                              { childList: true } );
         }
      }
   }   // flyout()



   function furnish( $area ) {
      // Divert link targets on document
      // Precondition:
      //    document ready
      //    $area  -- jQuery object of current $content
      // Uses:
      //    >  Config.kind
      //    >  Config.start
      //    (fiat)
      //    (fit)
      //    (flyout)
      // Remark: May be used as event handler -- 'this' is not accessed
      // 2016-04-03 PerfektesChaos@de.wikipedia
      var scope, $hypes;
      switch ( Config.kind ) {
         case 1 :
            $hypes = $area.find( ".external" );
            break;
         case 2 :
         case 3 :
            switch ( Config.special ) {
               case "Contributions" :
                  $hypes = $area.find( "ul,ol" );
                  break;
               case "LinkSearch" :
                  $hypes = $area.find( ".special" );
                  break;
               case "Whatlinkshere" :
                  $hypes = $area.find( "#mw-whatlinkshere-list" );
                  break;
               case "Recentchanges" :
               case "Watchlist" :
                  $hypes = $area.find( ".mw-changeslist" );
                  break;
               default:
                  $hypes = $area;
            }   // switch wgCanonicalSpecialPageName
            $hypes = $hypes.find( "a[href*=\"/\"]" );
            break;
         case 4 :
            $hypes      = $( "a[href*=\"/\"]" );
            Config.kind = 3;
            break;
      }   // switch kind
      $hypes.each( fiat );
      if ( Config.kind > 1 ) {
         scope = "#searchform, .searchbox";
         if ( Config.kind === 2  &&  Config.start === "history" ) {
            scope = scope + ", #mw-history-compare";
         }
         $( scope ).each( fit );
         mw.loader.using( [ "mediawiki.searchSuggest" ],
                          flyout );
      }
   }   // furnish()



   Config.features = function () {
      // Establish user configured appearance
      // Precondition:
      //    Prego user.options available
      // Uses:
      //    this
      //    >  .large
      //    >  .leave
      //    >  .mode
      //    >  Prego.supply
      //    >  .targets
      //     < Config.large
      //     < Config.leave
      //     < Config.mode
      //     < Prego.lib
      //     < Config.targets
      // 2015-10-03 PerfektesChaos@de.wikipedia
      var pars = [ [ "large", "boolean" ],
                   [ "leave", "boolean" ],
                   [ "mode",  "number"  ] ],
          n    = pars.length,
          i, s, v, vals;
      for ( i = 0;  i < n;  i++ ) {
         v = pars[ i ];
         s = v[ 0 ];
         if ( typeof CDV[ s ]  ===  v[ 1 ] ) {
            this[ s ] = CDV[ s ];
         } else {
            this[ s ] = false;
         }
      }   // for i
      Prego.lib = mw.libs[ Prego.supply ];
      if ( typeof Prego.lib  ===  "object"   &&
                  Prego.lib   &&
           typeof Prego.lib.fetch  ===  "function" ) {
         vals = Prego.lib.fetch( CDV.type );
         if ( vals   &&   typeof vals  ===  "object" ) {
            for ( i = 0;  i < n;  i++ ) {
               v = pars[ i ];
               s = v[ 0 ];
               if ( typeof vals[ s ]  ===  v[ 1 ] ) {
                  this[ s ] = vals[ s ];
               }
            }   // for i
         }
      } else {
         Prego.lib = false;
      }
      if ( typeof CDV.targets  ===  "object"   &&
           CDV.targets   &&
           this.mode ) {
         this.targets = { };
         for ( s in CDV.targets ) {
            v = CDV.targets[ s ];
            if ( v ) {
               switch ( typeof v ) {
                  case "string" :
                     v = [ v ];
                     break;
                  case "object" :
                     if ( typeof v.length  !==  "number" ) {
                        if ( typeof v.ignoreCase  ===  "boolean" ) {
                           v = [ v ];
                        } else {
                           v = false;
                        }
                     }
                     break;
                  default:
                     v = false;
               }   // switch typeof v
               if ( v ) {
                  this.targets[ s ] = v;
               }
            }
         }   // for s in .targets
      }
   };   // Config.features()



   Config.fire = function () {
      // Start possible actions on current page
      // Precondition:
      //    Resources available
      // Uses:
      //    >  Config.learn
      //    >  Prego.lib
      //    >  Config.special
      //    >  Config.large
      //    >  Config.start
      //    >  Config.leave
      //    >  window.location.href
      //    >  Config.mode
      //     < Config.kind
      //     < Config.source
      //     < Config.shift
      //    Config.features()
      //    Prego.form()
      //    mw.hook()
      //    (furnish)
      // Remark: May be used as event handler -- 'this' is not accessed
      // 2019-07-01 PerfektesChaos@de.wikipedia
      var i;
      Config.features();
      if ( Config.learn ) {
         Config.kind = 4;
         if ( Prego.lib ) {
            Prego.form();
         }
      } else {
         Config.kind = false;
         if ( typeof Config.special  ===  "string" ) {
            switch ( Config.special ) {
               case "Contributions" :
               case "LinkSearch" :
               case "Whatlinkshere" :
                  if ( Config.large ) {
                     Config.kind = 2;
                  }
                  break;
               default:
                  Config.kind = 2;
            }   // switch wgCanonicalSpecialPageName
         } else {
            switch ( Config.start ) {
               case "edit" :
               case "submit" :
                  Config.kind = 4;
                  $( ".cancelLink" ).hide();
                  break;
               case "history" :
                  if ( Config.large ) {
                     Config.kind = 2;
                  }
                  break;
               case "view" :
                  if ( Config.leave ) {
                     Config.kind = 1;
                  }
                  break;
            }   // switch wgAction
         }
      }
      if ( Config.kind ) {
         Config.source = window.location.href;
         i             = Config.source.indexOf( "#" );
         if ( i > 0 ) {
            Config.source = Config.source.substr( 0, i );
         }
         switch ( Config.mode ) {
            case 1 :
               Config.shift = "_blank";
               break;
            case 2 :
               Config.shift = "clickDiver";
               break;
            default:
               Config.shift = "_blank";
         }   // switch .mode
         mw.hook( "wikipage.content" ).add( furnish );
      }
   };   // Config.fire()



   Prego.fire = function () {
      // Prepare preferencesGadgetOptions availability
      // Postcondition:
      //    preferencesGadgetOptions requested, if not yet defined
      // Uses:
      //    this
      //     < Prego.supply
      //    mw.loader.getState()
      //    mw.loader.state()
      //    mw.loader.load()
      // 2018-08-30 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=604809"
                         + "&ctype=text/javascript",
                         "text/javascript" );
      }
   };   // Prego.fire()



   Prego.firing = function () {
      // Intermediate loading process step
      // Precondition:
      //    MW ressources are available
      // Uses:
      //    >  Prego.supply
      //    mw.hook()
      //    (Config.fire)
      // Remark: Used as event handler -- 'this' is not Prego
      // 2016-04-03 PerfektesChaos@de.wikipedia
      mw.hook( Prego.supply + ".ready" ).add( Config.fire );
   };   // Prego.firing()



   Prego.form = function () {
      // Equip Special:Blankpage PREGO page with entry and form
      // Uses:
      //    this
      //    >  Config.texts
      //    >  Config.pages
      //    >  .support
      //    >  .type
      //    >  Config.large
      //    >  Config.leave
      //    >  Config.mode
      //    >  Prego.lib
      //    mw.libs.preferencesGadgetOptions.form()
      // 2015-01-28 PerfektesChaos@de.wikipedia
      var pages = { },
          poly  = [ ],
          txt   = Config.texts,
          dialog, i, s;
      for ( i = 0;  i < Config.pages.length;  i++ ) {
         s          = Config.pages[ i ];
         pages[ s ] = "//" + s + ".wikipedia.org/wiki/" + CDV.support;
      }   // for i
      for ( i = 0;  i < 3;  i++ ) {
         poly.push( { val:  i,
                      show: txt[ "^^mode" + i ] } );
      }   // for i
      dialog = { script:  CDV.type,
                   show:    txt[ "^show" ],
                   support: pages,
                   suffix:  txt[ "^suffix" ],
                   opts:    [ { signature: "large",
                                type:      "checkbox",
                                show:      txt[ "^^large" ],
                                val:       Config.large
                              },
                              { signature: "leave",
                                type:      "checkbox",
                                show:      txt[ "^^leave" ],
                                val:       Config.leave
                              },
                              { signature: "mode",
                                type:      "radio",
                                show:      txt[ "^^mode" ],
                                val:       Config.mode,
                                poly:      poly } ] };
      Prego.lib.form( dialog );
   };   // Prego.form()



   CDV.fire = function () {
      // Start possible actions on current page
      // Uses:
      //     < CDV.signature
      //     < Config.learn
      //     < Config.special
      //     < Config.start
      //    mw.loader.getState()
      //    mw.loader.state()
      //    mw.config.get()
      //    Prego.fire()
      //    (Prego.firing)
      // Remark: May be used as event handler -- 'this' is not accessed
      // 2018-08-24 PerfektesChaos@de.wikipedia
      var env, launch, rls;
      if ( mw.loader.getState( CDV.signature ) !== "ready" ) {
         rls = { };
         rls[ CDV.signature ] = "ready";
         mw.loader.state( rls );
         env    = mw.config.get( [ "wgAction",
                                     "wgCanonicalSpecialPageName",
                                     "wgNamespaceNumber" ] );
         launch = true;
         Config.learn = false;
         if ( env.wgNamespaceNumber === -1 ) {
            Config.special = env.wgCanonicalSpecialPageName;
            switch ( Config.special ) {
               case "Blankpage" :
               case "Gadgets" :
                  Config.learn = true;
                  break;
               case "Contributions" :
               case "EditWatchlist" :
               case "LinkSearch" :
               case "Recentchanges" :
               case "Watchlist" :
               case "Whatlinkshere" :
                  break;
               default:
                  launch = false;
            }   // switch wgCanonicalSpecialPageName
         } else {
            Config.start = env.wgAction;
         }
         if ( launch ) {
            Prego.fire();
            mw.loader.using( [ "user",
                               "user.options" ],
                             Prego.firing );
         }
      }
   };   // .fire()



   CDV.fire();   // autorun
}( window.mediaWiki, window.jQuery ) );



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

/// EOF </nowiki>   clickDivertimento/d.js