Jump to content

User:PerfektesChaos/js/fragmentAnchors/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.
/// Gadget/fragmentAnchors/d.js
//  Mark anchors in HTML page and check validity
/// 2021-07-30 PerfektesChaos@de.wikipedia
//  ResourceLoader: compatible;
//    dependencies: user, mediawiki.util,
//                  oojs, oojs-ui-core, oojs-ui-widgets
/// Fingerprint:    #0#0#
/// Documentation:  [[w:en:User:PerfektesChaos/js/fragmentAnchors]]
/// @license:       CC-by-sa/4.0 GPLv3
/// <nowiki>
/* global window: false                                                */
/* jshint forin: false,
          bitwise:true, curly:true, eqeqeq:true, latedef:true,
          laxbreak:true,
          nocomma:true, strict:true, undef:true, unused:true           */
( function ( mw, $ ) {
   "use strict";
   var Version = -2.7,
       FANCY   = "fragmentAnchors",
       FASC    = { cfg:      { },
                   siblings: "error-repeated-id",
                   source0:  "6/62/Anchor_pictogram.svg",
                   source1:  "d/d6/Anchor_pictogram_red.svg",
                   unStart:  [ "wpTextbox", "/maplink/", "Anker:" ],
                   vsn:      Version
                 },   // Fragment Anchors Show Check (portable)
       EXPORT  = { },
       OO;



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



   function facet( $area ) {
      // Furnish page content area
      // Precondition:
      //    $area   -- jQuery object with content
      // Uses:
      //    >  FASC.locked
      //     < FASC.$content
      //     < FASC.$exclude
      //    mw.hook()
      //    FASC.furnish()
      // 2016-04-24 PerfektesChaos@de.wikipedia
      mw.hook( "wikipage.content" ).remove( facet );
      FASC.$content = $area;
      if ( FASC.locked ) {
         FASC.$exclude = false;
      } else {
         FASC.$exclude = FASC.$content.find( "form" );
      }
      FASC.furnish();
   }   // facet()



   function facility() {
      // All components ready; furnish page
      // Uses:
      //    >  FASC.large
      //     < OO
      //     < FASC.$content
      //    FASC.furnish()
      //    mw.hook()
      //    (facet)
      // 2016-09-01 PerfektesChaos@de.wikipedia
      OO = window.OO;
      if ( FASC.large ) {
         FASC.$content = false;
         FASC.$exclude = false;
         FASC.furnish();
      } else {
         mw.hook( "wikipage.content" ).add( facet );
      }
   }   // facility()



   function fiat() {
      // Portlet or other command has been activated
      // Uses:
      //    >  FASC.cfg.$portlet
      //     < FASC.cfg.live
      //    mw.loader.using()
      //    (facility)
      // 2016-09-01 PerfektesChaos@de.wikipedia
      FASC.cfg.live = false;
      if ( typeof FASC.cfg.$portlet  ===  "object" ) {
         FASC.cfg.$portlet.hide();
      }
      mw.loader.using( [ "oojs",
                         "oojs-ui-core",
                         "oojs-ui-widgets" ],
                       facility );
   }   // fiat()



   function fire() {
      // Initialize system in MediaWiki environment
      // Uses:
      //    >  Version
      //    >  EXPORT.fetch
      //    >  EXPORT.fire
      //    >< FANCY
      //    >< mw.libs
      //     < FANCY.type
      //     < FANCY.doc
      //     < FANCY.vsn
      //     < FANCY.fetch
      //     < FANCY.fire
      //     < FASC.locked
      //     < FASC.sign
      //     < FASC.cfg.live
      //    mw.loader.getState()
      //    mw.loader.state()
      //    mw.config.get()
      //    mw.loader.using()
      //    (FASC.fire)
      // 2018-08-24 PerfektesChaos@de.wikipedia
      var signature = "ext.gadget." + FANCY,
          env, rls;
      if ( mw.loader.getState( signature ) !== "ready" ) {
         rls = { };
         rls[ signature ] = "ready";
         mw.loader.state( rls );
         if ( typeof mw.libs[ FANCY ]  !==  "object"   ||
              !      mw.libs[ FANCY ] ) {
            mw.libs[ FANCY ] = { };
         }
         mw.libs[ FANCY ].type = FANCY;
         FANCY                 = mw.libs[ FANCY ];
         FANCY.vsn     = Version;
         FANCY.doc     = "w:en:User:PerfektesChaos/js/" + FANCY.type;
         FANCY.doc     = "[[" + FANCY.doc + "]]";
         FANCY.fetch   = EXPORT.fetch;
         FANCY.fire    = EXPORT.fire;
         env           = mw.config.get( [ "wgAction",
                                          "wgPageContentModel" ] );
         FASC.cfg.live = false;
         if ( env.wgPageContentModel === "wikitext" ) {
            FASC.locked   = ( env.wgAction === "view" );
            FASC.sign     = FANCY.type;
            mw.loader.using( [ "user",
                               "mediawiki.util" ],
                             FASC.fire );
         }
      }
   }   // fire()



   function freshed() {
      // Document content has been changed; show portlet link again
      // Uses:
      //     < FASC.cfg.live
      //    >  FASC.cfg.live
      // 2016-04-22 PerfektesChaos@de.wikipedia
      FASC.cfg.live = true;
      FASC.cfg.$portlet.show();
   }   // freshed()



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



   EXPORT.fetch = function() {
      // Retrieve list of anchors in page
      // Precondition:
      //    mw.hook .ready
      // Postcondition:
      //    Returns Array with three elements
      //             [0] Array with strings of all valid anchors
      //             [1] Object with strings of all undesired anchors
      //                 assigned to number of occurrences, or false
      //             [2] Object with strings of all broken inner links
      //                 assigned to number of occurrences, or false
      //       false if not yet ready
      // Uses:
      //    fiat()
      //    >  FASC.cfg.live
      //    >  FASC.total
      //    >  FASC.dup
      //    >  FASC.want
      //     < FASC.learn
      // 2016-04-22 PerfektesChaos@de.wikipedia
      var dup, r, s;
      if ( FASC.cfg.live ) {
         FASC.learn = false;
         fiat();
         if ( FASC.dup ) {
            dup = { };
            for ( s in FASC.dup ) {
               dup[ s ] = FASC.dup[ s ].length;
            }   // for s in dup
         } else {
            dup = false;
         }
         r = [ FASC.total, dup, FASC.want ];
      } else {
         r = false;
      }
      return r;
   };   // EXPORT.fetch()



   EXPORT.fire = function() {
      // Trigger page decoration from external command
      // Precondition:
      //    mw.hook .ready
      // Postcondition:
      //    Returns false if not yet ready, or already executed
      // Uses:
      //    >  FASC.cfg.live
      //    (fiat)
      // 2016-04-18 PerfektesChaos@de.wikipedia
      var r = FASC.cfg.live;
      if ( r ) {
         fiat();
      }
      return r;
   };   // EXPORT.fire()



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




   FASC.cfg.escape = function( anchor ) {
      // Interface MW: Escape HTML syntax
      // Precondition:
      //    anchor  -- string with anchor, will be escaped
      // Postcondition:
      //    Returns string
      // Uses:
      //    mw.html.escape()
      // 2016-04-18 PerfektesChaos@de.wikipedia
      return mw.html.escape( anchor );
   };   // FASC.cfg.escape()



   FASC.cfg.fair = function( anchor, allow ) {
      // Interface MW: Reformat anchor
      // Precondition:
      //    anchor  -- string with anchor in page, starting with '#'
      //    allow   -- true, if URI restrictions kept allowing URL
      //               false, if maximum adaption for human eyes
      // Postcondition:
      //    Returns string with anchor for display
      // Uses:
      //    >< FASC.cfg.wikiAnchor
      // 2018-01-28 PerfektesChaos@de.wikipedia
      var r, s;
      if ( allow ) {
         r = anchor;
      } else {
         r = anchor.replace( /_/g, " " );
      }
      if ( typeof FASC.cfg.wikiAnchor  !==  "object" ) {
         s = "[0-9A-Fa-f]";
         s = "\\.(" + s + s + ")";
         FASC.cfg.wikiAnchor = new RegExp( s, "g" );
      }
      try {
         s = r.replace( FASC.cfg.wikiAnchor, "%$1" );
         r = decodeURIComponent( s );
      } catch( e ) {
      }
      return r;
   };   // FASC.cfg.fair()



   FASC.cfg.familiar = function( anchor, $at ) {
      // Interface MW: Check anchor for duplicated sibling
      // Precondition:
      //    anchor  -- string with anchor in page, starting with '#'
      //    $at     -- true, if maximum adaption for human eyes
      // Postcondition:
      //    Returns true, if duplicated sibling
      // Uses:
      //    FASC.cfg.fair()
      // 2018-01-28 PerfektesChaos@de.wikipedia
      var s = FASC.cfg.fair( anchor, true ),
          r, $e;
      if ( s !== anchor  &&  $at.is( "span" ) ) {
         $e = $at.next();
         r  = ( $e.is( "span" )
                &&   "#" + $e.attr( "id" )  ===  s );
         if ( ! r ) {
            $e = $at.prev();
            r  = ( $e.is( "span" )
                   &&   "#" + $e.attr( "id" )  ===  s );
         }
      }
      return r;
   };   // FASC.cfg.familiar()



   FASC.cfg.fancy = function( anchor ) {
      // Interface MW: Decorate anchor for c&p
      // Precondition:
      //    anchor  -- string with decoded anchor, starting with '#'
      // Postcondition:
      //    Returns string with decorated anchor for c&p
      // 2016-02-26 PerfektesChaos@de.wikipedia
      return "[[" + anchor + "]]";
   };   // FASC.cfg.fancy()



   FASC.cfg.fire = function() {
      // Interface MW: Initialize HTML document
      // Precondition:
      //    document.ready
      // Uses:
      //    mw.util.addPortletLink()
      //    FASC.$facet()
      //    fiat()
      //    mw.hook()
      //    >  FANCY.large
      //    >  FANCY.launch
      //    >  FANCY.lock
      //    >  FASC.sign
      //    >  FANCY.type
      //     < FASC.$body
      //     < FASC.large
      //     < FASC.learn
      //     < FASC.cfg.$portlet
      //     < FASC.cfg.live
      //    (freshed)
      //    (fiat)
      // 2016-04-22 PerfektesChaos@de.wikipedia
      var launch, lock, portlet;
      FASC.$body = $( "body" );
      if ( typeof FANCY.large  ===  "boolean" ) {
         FASC.large = FANCY.large;
      }
      if ( typeof FANCY.launch  ===  "boolean" ) {
         launch = FANCY.launch;
      }
      if ( typeof FANCY.lock  ===  "boolean" ) {
         lock = FANCY.lock;
      }
      FASC.learn = true;
      if ( ! ( lock  || launch ) ) {
         portlet = mw.util.addPortletLink( "p-tb",
                                           "#",
                                           String.fromCharCode( 8201 ),
                                           "t-" + FASC.sign );
         FASC.cfg.$portlet = $( portlet );
         FASC.cfg.$portlet.append( FASC.$facet() );
         FASC.cfg.$portlet.click( fiat );
         FASC.cfg.$portlet.attr( { title: FASC.sign + " " + FASC.vsn } );
         mw.hook( "wikipage.content" ).add( freshed );
      }
      mw.hook( FANCY.type + ".ready" ).fire( FANCY );
      if ( launch ) {
         fiat();
      } else {
         FASC.cfg.live = true;
      }
   };   // FASC.cfg.fire()



   FASC.cfg.$flag = function() {
      // Interface MW: Element before which error summary may be inserted
      // Postcondition:
      //    Returns jQuery element, or false
      // 2016-02-26 PerfektesChaos@de.wikipedia
      return $( "h1" ).eq( 0 );
   };   // FASC.cfg.$flag()



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



   FASC.$facet = function ( alert, augment ) {
      // Create image element for mark
      // Precondition:
      //    alert    -- true: yellow background
      //    augment  -- true: red symbol
      // Postcondition:
      //    Returns jQuery object
      // Uses:
      //    FASC.$facet()
      //    >  FASC.source0
      //    >  FASC.source1
      // 2016-04-18 PerfektesChaos@de.wikipedia
      var m  = ( alert || augment  ?  1  :  0 ),
          n  = ( alert ? 20 : 12 ),
          s  = FASC[ "source" + m ],
          $r = $( "<img />" );
      $r.attr( { alt: "id?",
                 src: "https://upload.wikimedia.org/"
                      + "wikipedia/commons/thumb/"
                      + s + "/"
                      + n + "px-" + s.substr( 5 ) + ".png" } );
      $r.css( { "height": n,
                "width":  n } );
      if ( alert ) {
         $r.css( { "background-color": "#FFFF00",
                   "border":           "#FF0000 2px solid",
                   "padding":          "1px" } );
      }
      return $r;
   };   // FASC.$facet()



   FASC.$factory = function ( about ) {
      // Create clickable jQuery element for anchor mark
      // Precondition:
      //    about  -- bubble
      // Postcondition:
      //    Returns jQuery object
      // Uses:
      //    >  FASC.show
      //    >  FASC.siblings
      //    >< FASC.badges
      //    FASC.$facet()
      //    (FASC.flip)
      // 2017-03-19 PerfektesChaos@de.wikipedia
      var badge = FASC.badges[ about.mode ],
          $i, $r;
      if ( ! badge ) {
         badge = { };
         badge.$i = FASC.$facet( ( about.mode === 1 ),
                                 ( about.mode === 2 ) );
         badge.$i.addClass( FASC.show );
         if ( about.mode === 1 ) {
            badge.$i.addClass( FASC.siblings );
         }
         badge.$s = $( "<span>" );
         badge.$s.css( { "font-size": "25%" } )
                 .text( " " );
         badge.$r = $( "<span>" );
         badge.$r.append( badge.$s );
         FASC.badges[ about.mode ] = badge;
      }
      $r = badge.$r.clone();
      $i = badge.$i.clone();
      $r.append( $i )
        .append( badge.$s.clone() );
      $i.hover( function ( activity ) {
                   FASC.flip( activity, about, 0, true );
                   // Returns always false, stop the bubbling
                   return false;
                },
                function ( activity ) {
                   FASC.flip( activity, about, 0, false );
                   // Returns always false, stop the bubbling
                   return false;
                } );
      $i.click( function ( activity ) {
                   FASC.flip( activity, about, 1 );
                   // Returns always false, stop the bubbling
                   return false;
                } );
      about.$span = $r;
      return $r;
   };   // FASC.$factory()



   FASC.$failure = function ( anchor ) {
      // Create jQuery element for broken inner link mark
      // Precondition:
      //    anchor  -- string with anchor, starting with '#'
      // Postcondition:
      //    Returns jQuery object
      // Uses:
      //    >  FASC.single
      // 2016-04-20 PerfektesChaos@de.wikipedia
      var $r = $( "<span>" ),
          $s = $( "<span>" );
      $s.css( { "white-space": "nowrap" } );
      $s.css( { "font-size": "25%" } );
      $s.text( " " );
      $r.append( $s );
      $s = $( "<span>" );
      $s.addClass( FASC.single );
      $s.css( { "background-color": "#FFFF00",
                "border":           "#FF0000 2px solid",
                "color":            "#FF0000",
                "font-size":        "120%",
                "font-weight":      "bold",
                "padding-left":     "0.2em",
                "padding-right":    "0.2em" } );
      $s.attr( { title: anchor } );
      $s.text( "#" );
      $r.append( $s );
      $s = $( "<span>" );
      $s.css( { "font-size": "25%" } );
      $s.text( " " );
      $r.append( $s );
      return $r;
   };   // FASC.$failure()



   FASC.family = function ( all ) {
      // Filter set of anchor IDs to children
      // Precondition:
      //    all  -- object with anchors
      // Postcondition:
      //    Returns object with reduced entries
      // Uses:
      //    >  FASC.$content
      //    >  FASC.$exclude
      //    >< FASC.reApos
      // 2021-07-30 PerfektesChaos@de.wikipedia
      var r = { },
          s, seek, $e;
      for ( s in all ) {
         if ( all[ s ] ) {
            if ( FASC.$content ) {
               if ( typeof FASC.reApos  !==  "object" ) {
                  FASC.reApos = new RegExp( "'", "g" );
               }
               seek = "[id='"
                      + s.substr( 1 ).replace( FASC.reApos, "\\'" )
                      + "']";
               try {
                  $e = FASC.$content.find( seek );
               } catch( e ) {
                  $e = false;
               }
               if ( $e   &&
                    $e.length   &&
                    ! ( FASC.$exclude   &&
                        FASC.$exclude.find( seek ).length ) ) {
                  r[ s ] = $e;
               }
            } else {
               r[ s ] = all[ s ];
            }
         }
      }   // for s in all
      return r;
   };   // FASC.family()



   FASC.fiat = function ( about, action ) {
      // Create popup for anchor mark
      // Precondition:
      //    about   -- bubble
      //    action  -- 0: hoverIn/hoverOut; 1: click
      // Postcondition:
      //    Returns OO popup object
      // Uses:
      //    >  FASC.sign
      //    >  FASC.$body
      //    FASC.cfg.escape()
      //    FASC.cfg.fancy()
      //    OO.ui.PopupWidget()
      // 2017-03-19 PerfektesChaos@de.wikipedia
      var illusive = 0.75,
          margin   = 10,
          options  = { align:              "center",
                       anchor:             true,
                       horizontalPosition: "center",
                       padded:             false,
                       verticalPosition:   "below" },
          show     = about.sign,
          sign     = FASC.sign + ( action ? "-t" : "-i" )
                               + about.id,
          $p       = $( "<span>" ),
          r;
      $p.css( { "left":     ( -0.5 * about.$span.innerWidth()  -  1 )
                            + "px",
                "position": "relative",
                "top":      "3px" } );
      about.$span.append( $p );
      options.$floatableContainer = $p;
      $p = $( "<span>" );
      if ( show ) {
         show = ( action ? "#" : "" )  +  FASC.cfg.escape( show );
      } else {
         show = "#";
      }
      if ( about.mode === 2 ) {
         $p.css( { "background-color": "#FFFF00",
                   "color":            "#FF0000",
                   "font-weight":      "bold",
                   "margin":           "0.2em",
                   "padding":          "0.4em" } )
           .text( show );
      } else {
         if ( show ) {
            if ( action ) {
               show     = FASC.cfg.fancy( show );
               illusive = 0.95;
            }
            $p.css( { "color":       "#000000",
                      "font-weight": "normal" } )
              .text( show );
         } else {
            $p.css( { "margin": "0.2em",
                      "width":  "2em" } )
              .text( String.fromCharCode( 160, 160 ) );
         }
      }
      $p.attr( { "id": sign } )
        .addClass( FASC.sign + "-text" )
        .css( { "font-family":  "sans-serif",
                "font-size":    "medium",
                "font-style":   "normal",
                "font-variant": "normal",
                "visibility":   "hidden" } );
      FASC.$body.append( $p );
      $p = $( "#" + sign );
      options.width = $p.outerWidth() + margin;
      $p.detach()
        .css( { "visibility": "visible" } );
      options.$content = $p;
      r = new OO.ui.PopupWidget( options );
      r.$floatable.attr( { "role": "tooltip" } )
                  .css( { "opacity":    illusive,
                          "padding":    "2px",
                          "text-align": "center" } );
      FASC.$body.append( r.$floatable );
      return r;
   };   // FASC.fiat()



   FASC.file = function ( anchor, alert, $a ) {
      // Register item, apply jQuery element as mark
      // Precondition:
      //    anchor  -- string with anchor, starting with '#'
      //    alert   -- true: duplicate or empty
      //    $a      -- jQuery anchor element to be equipped
      // Postcondition:
      //    Item has been registered, element became clickable
      // Uses:
      //    >< FASC.bubbles
      //    FASC.fine()
      //    FASC.$factory
      // 2017-03-19 PerfektesChaos@de.wikipedia
      var sign   = anchor.substr( 1 ),
          lapse  = ( ! FASC.fine( sign ) ),
          mode   = ( alert  ?  1  :  ( lapse ? 2 : 0 ) ),
          id     = FASC.bubbles.length,
          bubble = { id:      id,
                     mode:    mode,
                     popups:  [ false, false ],
                     sign:    sign,
                     live:    false,
                     $a:      $a,
                     $span:   false };
      FASC.bubbles.push( bubble );
      $a.attr( { "title": null } );
      $a.before( FASC.$factory( bubble ) );
   };   // FASC.file()



   FASC.filter = function ( anchor ) {
      // Ignore certain anchors
      // Precondition:
      //    anchor  -- string with anchor, starting with '#'
      // Postcondition:
      //    Returns true if anchor shall be maintained
      // Uses:
      //    >  FASC.unStart
      // 2016-04-24 PerfektesChaos@de.wikipedia
      var r = true,
          i, s;
      if ( FASC.unStart ) {
         for ( i = 0;  i < FASC.unStart.length;  i++ ) {
            s = FASC.unStart[ i ];
            if ( anchor.substr( 1, s.length )  ===  s ) {
               r = false;
               break;   // for i
            }
         }   // for i
      }
      return r;
   };   // FASC.filter()



   FASC.fine = function ( anchor ) {
      // Check syntactical compliance of a (decoded) anchor
      // Precondition:
      //    anchor  -- string with anchor, starting after '#'
      // Postcondition:
      //    Returns true if no complaints
      // Uses:
      //    >< FASC.reFine
      // 2016-04-17 PerfektesChaos@de.wikipedia
      var r = true,
          i;
      if ( typeof FASC.reFine  !==  "object" ) {
         FASC.reFine = [ new RegExp( "^\\s" ),
                         new RegExp( "\\s$" ),
                         new RegExp( "^\\d" ),
                         new RegExp( "[<>'\"#%\\\\]" ),
                         new RegExp( "\\?\\?" ) ];
      }
      for ( i = 0;  i < FASC.reFine.length;  i++ ) {
         if ( FASC.reFine[ i ].test( anchor ) ) {
            r = false;
            break;   // for i
         }
      }   // for i
      return r;
   };   // FASC.fine()



   FASC.fire = function () {
      // Initialize FASC system
      // Uses:
      //    >  FASC.unStart
      //    >  FASC.sign
      //    >< FASC.large
      //    >< FASC.unStart
      //     < FASC.badges
      //     < FASC.reFine
      //     < FASC.scope
      //     < FASC.show
      //    (FASC.cfg.fire)
      // 2016-09-01 PerfektesChaos@de.wikipedia
      FASC.badges = [ false, false, false ];
      if ( typeof FASC.large  !==  "boolean" ) {
         FASC.large = false;
      }
      if ( typeof FASC.unStart  !==  "object" ) {
         FASC.unStart = false;
      }
      FASC.reFine = false;
      FASC.scope  = FASC.sign + "-inner";
      FASC.show   = FASC.sign + "-mark";
      FASC.single = FASC.show + " " + FASC.sign + "-broken";
      $( FASC.cfg.fire );
   };   // FASC.fire()



   FASC.flag = function () {
      // Inform user on multiplied anchors
      // Uses:
      //    FASC.cfg.$flag()
      //    >  FASC.dup
      //    >  FASC.want
      //    >  FASC.sign
      //    >  FASC.show
      // 2021-01-18 PerfektesChaos@de.wikipedia
      var $before = FASC.cfg.$flag(),
          dup, s, $box, $li, $ul;
      if ( $before ) {
         $box = $( "<div>" );
         $ul  = $( "<ul>" );
         for ( s in FASC.dup ) {
            dup = FASC.dup[ s ];
            $li = $( "<li>" );
            $li.text( dup.length
                      + String.fromCharCode( 215 ) + " " + s );
            $ul.append( $li );
         }   // for s in FASC.dup
         for ( s in FASC.want ) {
            $li = $( "<li>" );
            $li.text( String.fromCharCode( 8722 ) + FASC.want[ s ]
                      + String.fromCharCode( 215 ) + " " + s );
            $ul.append( $li );
         }   // for s in FASC.want
         $box.css( { "border":        "#FF0000 2px solid",
                     "color":         "#FF0000",
                     "margin-bottom": "1em",
                     "margin-top":    "1em",
                     "padding":       "0.5em" } );
         $box.attr( { "id":  FASC.sign + "-errors" } );   // legacy
         $box.addClass( FASC.show
                        + " error "
                        + FASC.sign + "-errors" );
         $box.append( $ul );
         $before.before( $box );
      }
   };   // FASC.flag()



   FASC.flip = function ( activity, about, apply, activate ) {
      // Toggle hover or click on mark
      // Precondition:
      //    activity  -- event
      //    about     -- item in FASC.bubbles
      //    apply     -- 0: hoverIn/hoverOut;  1: click
      //    activate  -- true: hoverIn;  false: hoverOut
      // Uses:
      //    this  -- clicked element
      //    FASC.fiat()
      // 2017-03-19 PerfektesChaos@de.wikipedia
      var live   = about.live,
          popup  = about.popups[ apply ];
      if ( typeof activity  ===  "object"   &&   activity ) {
         if ( typeof activity.preventDefault  ===  "function" ) {
            activity.preventDefault();
         }
         if ( typeof activity.stopPropagation  ===  "function" ) {
            activity.stopPropagation();
         }
      }
      if ( ! popup ) {
         popup = FASC.fiat( about, apply );
         about.popups[ apply ] = popup;
         if ( apply  &&  ! about.popups[ 0 ] ) {
            about.popups[ 0 ] = FASC.fiat( about, 0 );
         }
      }
      if ( apply ) {
         about.popups[ 0 ].toggle( false );
         live = ! live;
         about.live = live;
         popup.toggle( live );
      } else if ( live ) {
         popup.toggle( false );
      } else {
         popup.toggle( activate );
      }
   };   // FASC.flip()



   FASC.furnish = function () {
      // Analyze HTML page, update inserted anchor marks etc.
      // Postcondition:
      //    Page has been equipped
      // Uses:
      //    >  FASC.show
      //    >  FASC.large
      //    >  FASC.locked
      //    >  FASC.scope
      //    >  FASC.learn
      //     < FASC.dup
      //     < FASC.bubbles
      //     < FASC.total
      //     < FASC.want
      //    FASC.filter()
      //    FASC.file()
      //    FASC.$failure()
      //    FASC.flag()
      //    FASC.cfg.familiar()
      //    FASC.cfg.fair()
      // 2018-01-29 PerfektesChaos@de.wikipedia
      var total  = { },
          $total = $( "[id]" ),
          dup, i, lapsus, s, $e, $inner;
      FASC.bubbles = [ ];
      FASC.dup     = { };
      FASC.total   = [ ];
      FASC.want    = false;
      $( "." + FASC.show ).remove();
      for ( i = 0;  i < $total.length;  i++ ) {
         $e = $total.eq( i );
         s  = "#" + $e.attr( "id" );
         if ( FASC.filter( s ) ) {
            if ( FASC.cfg.familiar( s, $e ) ) {
               s = false;
            }
         } else {
            s = false;
         }
         if ( s ) {
            if ( typeof total[ s ]  ===  "object" ) {
               if ( typeof FASC.dup[ s ]  !==  "object" ) {
                  FASC.dup[ s ] = [ total[ s ] ];
                  total[ s ]    = null;
               }
               FASC.dup[ s ].push( $e );
            } else {
               total[ s ] = $e;
            }
         }
      }   // for i
      $total = false;
      if ( typeof total[ "#" ]  ===  "object" ) {
         FASC.dup[ "#" ] = [ total[ "#" ] ];
         total[ "#" ]    = true;
      }
      for ( s in FASC.dup ) {
         lapsus = true;
         FASC.total.push( s );
         dup = FASC.dup[ s ];
         for ( i = 0;  i < dup.length;  i++ ) {
            $e = dup[ i ];
            if ( $e ) {
               FASC.file( s, true, $e );
            }
         }   // for i
         total[ s ] = false;
      }   // for s in dup
      if ( ! lapsus ) {
         FASC.dup = false;
      }
      if ( FASC.locked ) {
         $inner = $( "a[href^='#']" );
         for ( i = 0;  i < $inner.length;  i++ ) {
            $e = $inner.eq( i );
            s  = $e.attr( "href" );
            if ( s !== "#" ) {
               $e.addClass( FASC.scope );
               if ( typeof total[ s ]  !==  "object"   &&
                    FASC.filter( s ) ) {
                  $e.before( FASC.$failure( s ) );
                  if ( ! FASC.want ) {
                     FASC.want = { };
                  }
                  if ( typeof FASC.want[ s ]  ===  "number" ) {
                     FASC.want[ s ] = FASC.want[ s ] + 1;
                  } else {
                     FASC.want[ s ] = 1;
                  }
               }
            }
         }   // for i
      }
      if ( FASC.dup || FASC.want ) {
         FASC.flag();
      }
      total = FASC.family( total );
      for ( s in total ) {
         if ( typeof total[ s ]  ===  "object" ) {
            FASC.total.push( s );
            if ( FASC.learn ) {
               FASC.file( FASC.cfg.fair( s ),  false,  total[ s ] );
            }
         }
      }   // for s in total
   };   // FASC.furnish()



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



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



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