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
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

Videos

Youtube | Vimeo | Bing

Websites

Google | Yahoo | Bing

Encyclopedia

Google | Yahoo | Bing

Facebook